<commit_before>﻿angular.module('designer').controller('designerController', ['$scope', '$http', 'subscriptionRepository', function ($scope, $http, subscriptionRepository) {
    $scope.activeTab = 'report';

    $scope.init = function () {
        $scope.activeTab = 'report';
        $http.get('api/Designer/GetViewModel').
            success(function (data) {
                $scope.inputTypes = data.InputTypes;
                $scope.reportList = data.Reports;
                $scope.connections = data.Connections;
                $scope.lookupReports = data.LookupReports;
                $scope.accessLists = data.AccessLists;
                $scope.reportOwnerAccessLists = data.ReportOwnerAccessLists;
                $scope.settings = data.Settings;
                $scope.accessEditorViewModel = data.AccessEditorViewModel;
                $scope.SubscriptionEnabled = data.SubscriptionEnabled;
            }).
            error(function (data) {
                toastr.error("Couldn't get list of reports from server.", "Error");
            });
    };
    $scope.init();

    //Globals and help functions
    var regExParameterMatch = /(@\w+)/g;
    var parameterPositionHash = [];
    function updateCollection(collection, updatedEntity, deleted) {
        var index = collection.indexOf(_.find(collection, function (entity) { return entity.Id === updatedEntity.Id }));

        if (deleted) {
            collection.splice(index, 1);
        } else {
            if (index !== -1) {
                collection.splice(index, 1, updatedEntity);
            } else {
                collection.push(updatedEntity);
            }
        }
        $scope.$apply();
    }

    //Reports
    $scope.reportDataChanged = function () {
        if ($scope.SubscriptionEnabled)
            createOriginalParameterBackup();

        if ($scope.SubscriptionEnabled && !$scope.report.hasLoadedSubscriptions) {//we dont want this to run on every keyup.. and yes i know we reload subs on every save, but i think that is correct.
            $scope.report.hasLoadedSubscriptions = true;
            var report = $scope.report;
            report.warnForParameterChanges = true;
            subscriptionRepository.allForReport(report.Id).success(function (data) {
                report.SubscriptionCount = data.length;
                report.warnForParameterChanges = data.length > 0;
            }).error(function () {
                toastr.warning('Could not load subscriptions for the report. Validation will assume there are subscriptions for your safety.');
            });
        }

        $scope.latestSql = $scope.report.Sql;
        parameterPositionHash = [];
        while (match = regExParameterMatch.exec($scope.latestSql)) {
            var existingparam = _.findWhere($scope.report.Parameters, { SqlKey: match[0] });
            if (existingparam !== undefined) {
                parameterPositionHash[match.index] = existingparam.SqlKey;
            }
        }
    };
    $scope.analyzeSQL = function () {
        var currentSQL = $scope.report.Sql;
        var match;
        var currentPosition = $('#sqlarea').prop('selectionStart');
        var foundMatches = [];

        while (match = regExParameterMatch.exec(currentSQL)) {
            var existingparam = _.findWhere($scope.report.Parameters, { SqlKey: match[0] });
            if (existingparam === undefined) {
                if (currentPosition >= match.index && currentPosition <= match.index + match[0].length) {
                    var nameOfExisting = parameterPositionHash[match.index];
                    existingparam = _.findWhere($scope.report.Parameters, { SqlKey: nameOfExisting });
                    if (existingparam !== undefined) {
                        existingparam.SqlKey = match[0];
                    } else {
                        $scope.addNewParameter(match[0]);
                    }
                } else {
                    $scope.addNewParameter(match[0]);
                }
            }
            foundMatches.push(match[0]);
        }

        //transform from and to-parameters to a period-parameter.
        var periodIsPresentAndValid = false;
        var periodFrom = _.findWhere($scope.report.Parameters, { SqlKey: '@from' });
        var periodTo = _.findWhere($scope.report.Parameters, { SqlKey: '@to' });
        var periodFromAndTo = _.findWhere($scope.report.Parameters, { SqlKey: '@from_@to' });
        if (periodFrom !== undefined && periodTo !== undefined) {
            $scope.report.Parameters.splice($scope.report.Parameters.indexOf(periodTo), 1);
            periodIsPresentAndValid = true;
            if (periodFromAndTo === undefined) {
                periodFrom.SqlKey = '@from_@to';
                periodFrom.InputType = 3;
            } else { //combined parameter already exists.
                $scope.report.Parameters.splice($scope.report.Parameters.indexOf(periodFrom), 1);
            }
        }

        //Delete params no longer in the SQL
        var i = $scope.report.Parameters.length;
        while (i--) {
            if (_.indexOf(foundMatches, $scope.report.Parameters[i].SqlKey) === -1) {
                if ($scope.report.Parameters[i].SqlKey === '@from_@to') {
                    if (!periodIsPresentAndValid) {
                        $scope.report.Parameters.splice(i, 1);
                    }
                } else {
                    $scope.report.Parameters.splice(i, 1);
                }
            }
        }

        $scope.reportDataChanged();
    };

    function parameterChecksum(p) {
        var o = { InputType: p.InputType };

        if (p.Value)
            o.hasDefaultValue = true;

        return o;
    }

    function createOriginalParameterBackup(force) {
        if (!force && $scope.report.parameterChecksums)
            return;

        var backup = {};
        $scope.report.Parameters.forEach(function (p) {
            backup[p.SqlKey] = parameterChecksum(p);
        });

        $scope.report.parameterChecksums = backup;
    }

    function isChecksumsMatching(origin, current) {
        var valid = true;
        //this works based on the fact that currently we dont care if checksum params are added to current, because the only addition is a default value which will obviously work.
        Object.keys(origin).forEach(function (k) {
            if (origin[k] !== current[k]) {
                valid = false;
            }
        });

        return valid;
    }

    function hasMadeInvalidParameterChanges() {
        var invalid = false;
        $scope.report.Parameters.forEach(function (p) {
            var checksum = $scope.report.parameterChecksums[p.SqlKey];
            if (checksum) {
                if (!isChecksumsMatching(checksum, parameterChecksum(p))) {
                    invalid = true;
                }
            } else {
                if (p.Value === undefined || p.Value === '') {
                    invalid = true;
                }
            }
        });

        return invalid;
    }

    $scope.addNewReport = function () {
        $scope.report = { Id: null, Parameters: [], TemplateEditorAccessStyle: 0, SubscriptionAccessStyle: 0 };
    };
    $scope.addNewParameter = function (keyOfParameter) {
        //console.debug('new parameter');
        $scope.report.Parameters.push({ SqlKey: keyOfParameter, Value: "", InputType: 0, Mandatory: false, Label: "", HelpText: "" });<commit_msg>added default values on create new report<commit_after>﻿angular.module('designer').controller('designerController', ['$scope', '$http', 'subscriptionRepository', function ($scope, $http, subscriptionRepository) {
    $scope.activeTab = 'report';

    $scope.init = function () {
        $scope.activeTab = 'report';
        $http.get('api/Designer/GetViewModel').
            success(function (data) {
                $scope.inputTypes = data.InputTypes;
                $scope.reportList = data.Reports;
                $scope.connections = data.Connections;
                $scope.lookupReports = data.LookupReports;
                $scope.accessLists = data.AccessLists;
                $scope.reportOwnerAccessLists = data.ReportOwnerAccessLists;
                $scope.settings = data.Settings;
                $scope.accessEditorViewModel = data.AccessEditorViewModel;
                $scope.SubscriptionEnabled = data.SubscriptionEnabled;
            }).
            error(function (data) {
                toastr.error("Couldn't get list of reports from server.", "Error");
            });
    };
    $scope.init();

    //Globals and help functions
    var regExParameterMatch = /(@\w+)/g;
    var parameterPositionHash = [];
    function updateCollection(collection, updatedEntity, deleted) {
        var index = collection.indexOf(_.find(collection, function (entity) { return entity.Id === updatedEntity.Id }));

        if (deleted) {
            collection.splice(index, 1);
        } else {
            if (index !== -1) {
                collection.splice(index, 1, updatedEntity);
            } else {
                collection.push(updatedEntity);
            }
        }
        $scope.$apply();
    }

    //Reports
    $scope.reportDataChanged = function () {
        if ($scope.SubscriptionEnabled)
            createOriginalParameterBackup();

        if ($scope.SubscriptionEnabled && !$scope.report.hasLoadedSubscriptions) {//we dont want this to run on every keyup.. and yes i know we reload subs on every save, but i think that is correct.
            $scope.report.hasLoadedSubscriptions = true;
            var report = $scope.report;
            report.warnForParameterChanges = true;
            subscriptionRepository.allForReport(report.Id).success(function (data) {
                report.SubscriptionCount = data.length;
                report.warnForParameterChanges = data.length > 0;
            }).error(function () {
                toastr.warning('Could not load subscriptions for the report. Validation will assume there are subscriptions for your safety.');
            });
        }

        $scope.latestSql = $scope.report.Sql;
        parameterPositionHash = [];
        while (match = regExParameterMatch.exec($scope.latestSql)) {
            var existingparam = _.findWhere($scope.report.Parameters, { SqlKey: match[0] });
            if (existingparam !== undefined) {
                parameterPositionHash[match.index] = existingparam.SqlKey;
            }
        }
    };
    $scope.analyzeSQL = function () {
        var currentSQL = $scope.report.Sql;
        var match;
        var currentPosition = $('#sqlarea').prop('selectionStart');
        var foundMatches = [];

        while (match = regExParameterMatch.exec(currentSQL)) {
            var existingparam = _.findWhere($scope.report.Parameters, { SqlKey: match[0] });
            if (existingparam === undefined) {
                if (currentPosition >= match.index && currentPosition <= match.index + match[0].length) {
                    var nameOfExisting = parameterPositionHash[match.index];
                    existingparam = _.findWhere($scope.report.Parameters, { SqlKey: nameOfExisting });
                    if (existingparam !== undefined) {
                        existingparam.SqlKey = match[0];
                    } else {
                        $scope.addNewParameter(match[0]);
                    }
                } else {
                    $scope.addNewParameter(match[0]);
                }
            }
            foundMatches.push(match[0]);
        }

        //transform from and to-parameters to a period-parameter.
        var periodIsPresentAndValid = false;
        var periodFrom = _.findWhere($scope.report.Parameters, { SqlKey: '@from' });
        var periodTo = _.findWhere($scope.report.Parameters, { SqlKey: '@to' });
        var periodFromAndTo = _.findWhere($scope.report.Parameters, { SqlKey: '@from_@to' });
        if (periodFrom !== undefined && periodTo !== undefined) {
            $scope.report.Parameters.splice($scope.report.Parameters.indexOf(periodTo), 1);
            periodIsPresentAndValid = true;
            if (periodFromAndTo === undefined) {
                periodFrom.SqlKey = '@from_@to';
                periodFrom.InputType = 3;
            } else { //combined parameter already exists.
                $scope.report.Parameters.splice($scope.report.Parameters.indexOf(periodFrom), 1);
            }
        }

        //Delete params no longer in the SQL
        var i = $scope.report.Parameters.length;
        while (i--) {
            if (_.indexOf(foundMatches, $scope.report.Parameters[i].SqlKey) === -1) {
                if ($scope.report.Parameters[i].SqlKey === '@from_@to') {
                    if (!periodIsPresentAndValid) {
                        $scope.report.Parameters.splice(i, 1);
                    }
                } else {
                    $scope.report.Parameters.splice(i, 1);
                }
            }
        }

        $scope.reportDataChanged();
    };

    function parameterChecksum(p) {
        var o = { InputType: p.InputType };

        if (p.Value)
            o.hasDefaultValue = true;

        return o;
    }

    function createOriginalParameterBackup(force) {
        if (!force && $scope.report.parameterChecksums)
            return;

        var backup = {};
        $scope.report.Parameters.forEach(function (p) {
            backup[p.SqlKey] = parameterChecksum(p);
        });

        $scope.report.parameterChecksums = backup;
    }

    function isChecksumsMatching(origin, current) {
        var valid = true;
        //this works based on the fact that currently we dont care if checksum params are added to current, because the only addition is a default value which will obviously work.
        Object.keys(origin).forEach(function (k) {
            if (origin[k] !== current[k]) {
                valid = false;
            }
        });

        return valid;
    }

    function hasMadeInvalidParameterChanges() {
        var invalid = false;
        $scope.report.Parameters.forEach(function (p) {
            var checksum = $scope.report.parameterChecksums[p.SqlKey];
            if (checksum) {
                if (!isChecksumsMatching(checksum, parameterChecksum(p))) {
                    invalid = true;
                }
            } else {
                if (p.Value === undefined || p.Value === '') {
                    invalid = true;
                }
            }
        });

        return invalid;
    }

    $scope.addNewReport = function () {
        $scope.report = { Id: null, Parameters: [], TemplateEditorAccessStyle: 0, SubscriptionAccessStyle: 0, ReportOwnerId: $scope.reportOwnerAccessLists[0].Id, AccessId: $scope.accessLists[0].Id };
    };
    $scope.addNewParameter = function (keyOfParameter) {
        //console.debug('new parameter');
        $scope.report.Parameters.push({ SqlKey: keyOfParameter, Value: "", InputType: 0, Mandatory: false, Label: "", HelpText: "" });
{'fraction_non_alphanumeric': 0.1189650573486263, 'fraction_numerical': 0.002800746865830888, 'mean_word_length': 1.9296737644071107, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, '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': '2888199', 'n_tokens_mistral': 3926, 'n_tokens_neox': 3783, 'n_words': 820}