<commit_before>(function () {
  'use strict';

  var directives = angular.module('redash.directives');

  // Angular strips data- from the directive, so data-source-form becomes sourceForm...
  directives.directive('sourceForm', ['$http', 'growl', function ($http, growl) {
    return {
      restrict: 'E',
      replace: true,
      templateUrl: '/views/data_sources/form.html',
      scope: {
        'dataSource': '='
      },
      link: function ($scope) {
        var setType = function(types) {
          if ($scope.dataSource.type === undefined) {
            $scope.dataSource.type = types[0].type;
            return types[0];
          }

          $scope.type = _.find(types, function (t) {
            return t.type == $scope.dataSource.type;
          });
        };

        $scope.files = {};

        $scope.$watchCollection('files', function() {
          _.each($scope.files, function(v, k) {
            if (v) {
              $scope.dataSource.options[k] = v.base64;
            }
          });
        });

        $http.get('api/data_sources/types').success(function (types) {
          setType(types);

          $scope.dataSourceTypes = types;

          _.each(types, function (type) {
            _.each(type.configuration_schema.properties, function (prop, name) {
              if (name == 'password' || name == 'passwd') {
                prop.type = 'password';
              }

              if (_.string.endsWith(name, "File")) {<commit_msg>Fix: data source loaded without properties<commit_after>(function () {
  'use strict';

  var directives = angular.module('redash.directives');

  // Angular strips data- from the directive, so data-source-form becomes sourceForm...
  directives.directive('sourceForm', ['$http', 'growl', '$q', function ($http, growl, $q) {
    return {
      restrict: 'E',
      replace: true,
      templateUrl: '/views/data_sources/form.html',
      scope: {
        'dataSource': '='
      },
      link: function ($scope) {
        var setType = function(types) {
          if ($scope.dataSource.type === undefined) {
            $scope.dataSource.type = types[0].type;
            return types[0];
          }

          $scope.type = _.find(types, function (t) {
            return t.type == $scope.dataSource.type;
          });
        };

        $scope.files = {};

        $scope.$watchCollection('files', function() {
          _.each($scope.files, function(v, k) {
            if (v) {
              $scope.dataSource.options[k] = v.base64;
            }
          });
        });

        var typesPromise = $http.get('api/data_sources/types');

        $q.all([typesPromise, $scope.dataSource.$promise]).then(function(responses) {
          var types = responses[0].data;
          setType(types);

          $scope.dataSourceTypes = types;

          _.each(types, function (type) {
            _.each(type.configuration_schema.properties, function (prop, name) {
              if (name == 'password' || name == 'passwd') {
                prop.type = 'password';
              }

              if (_.string.endsWith(name, "File")) {
{'fraction_non_alphanumeric': 0.15466237942122185, 'fraction_numerical': 0.0028938906752411574, 'mean_word_length': 1.9156513589503281, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, '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': '5213112', 'n_tokens_mistral': 909, 'n_tokens_neox': 879, 'n_words': 179}