summaryrefslogtreecommitdiff
path: root/horizon/static/framework/framework.module.js
blob: 16e901a4e7664d255e4ef38339f9030e81b5d3e5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
(function () {
  'use strict';

  angular
    .module('horizon.framework', [
      'horizon.framework.conf',
      'horizon.framework.util',
      'horizon.framework.widgets'
    ])
    .config(config)
    .run(run);

  config.$inject = [
    '$injector',
    '$provide',
    '$interpolateProvider',
    '$httpProvider',
    '$windowProvider'
  ];

  function config($injector, $provide, $interpolateProvider, $httpProvider, $windowProvider) {

    var path = $windowProvider.$get().STATIC_URL + 'framework/';
    $provide.constant('horizon.framework.basePath', path);

    // Replacing the default angular symbol
    // allow us to mix angular with django templates
    $interpolateProvider.startSymbol('{$');
    $interpolateProvider.endSymbol('$}');

    // Http global settings for ease of use
    $httpProvider.defaults.xsrfHeaderName = 'X-CSRFToken';
    $httpProvider.defaults.xsrfCookieName = 'csrftoken';
    $httpProvider.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';
    $httpProvider.defaults.headers.common['Content-Type'] = 'application/json;charset=utf-8';

    // NOTE(tsufiev): angular-ui/bootstrap v0.11.2 dropdownToggle directive
    // conflicts with the native Bootstrap data-toggle="dropdown" attribute
    // (see https://github.com/angular-ui/bootstrap/issues/2156).
    // This is fixed in 0.13, but before that it'd be valuable to ensure that
    // the same html markup works the same way with both versions of
    // angular-ui/bootstrap (0.11.2 and 0.13). Could be safely deleted once
    // Horizon migrates to angular-ui/bootstra v0.13
    if ($injector.has('dropdownToggleDirective')) {
      $provide.decorator('dropdownToggleDirective', patchDropdowns);
    }

    patchDropdowns.$inject = ['$delegate'];

    function patchDropdowns($delegate) {
      var directive = $delegate[0];
      directive.restrict = 'A';
      return $delegate;
    }

    // Global http error handler
    // if user is not authorized, log user out
    // this can happen when session expires
    $httpProvider.interceptors.push(redirect);
    $httpProvider.interceptors.push(stripAjaxHeaderForCORS);

    redirect.$inject = ['$q'];

    function redirect($q) {
      return {
        responseError: function (error) {
          if (error.status === 401) {
            var $window = $windowProvider.$get();
            $window.location.replace($window.WEBROOT + 'auth/logout');
          }
          return $q.reject(error);
        }
      };
    }

    stripAjaxHeaderForCORS.$inject = [];
    // Standard CORS middleware used in OpenStack services doesn't expect
    // X-Requested-With header to be set for requests and rejects requests
    // which have it. Since there is no reason to treat Horizon specially when
    // dealing handling CORS requests, it's better for Horizon not to set this
    // header when it sends CORS requests. Detect CORS request by presence of
    // X-Auth-Token headers which normally should be provided because of
    // Keystone authentication.
    function stripAjaxHeaderForCORS() {
      return {
        request: function(config) {
          if ('X-Auth-Token' in config.headers) {
            delete config.headers['X-Requested-With'];
          }
          return config;
        }
      };
    }
  }

  run.$inject = ['$window', '$rootScope'];

  function run($window, $rootScope) {
    $window.recompileAngularContent = recompileAngularContent;

    function recompileAngularContent($element) {
      function explicit($compile) {
        // NOTE(tsufiev): recompiling elements with ng-click directive spawns
        // a new 'click' handler even if there were some, so we need to cleanup
        // existing handlers before doing this.
        $element.find('[ng-click]').off('click');
        $compile($element)($rootScope);
      }
      explicit.$inject = ['$compile'];
      $element.injector().invoke(explicit);
    }
  }

})();