diff --git a/static/app/core/health.resource.js b/static/app/core/health.resource.js
new file mode 100644
index 000000000..1648f2eb3
--- /dev/null
+++ b/static/app/core/health.resource.js
@@ -0,0 +1,10 @@
+(function () {
+ 'use strict';
+
+ angular
+ .module('traefik.core.health', ['ngResource'])
+ .factory('Health', ['$resource', function ($resource) {
+ return $resource('/health');
+ }]);
+
+})();
diff --git a/static/app/core/providers.resource.js b/static/app/core/providers.resource.js
new file mode 100644
index 000000000..fb74329d9
--- /dev/null
+++ b/static/app/core/providers.resource.js
@@ -0,0 +1,10 @@
+(function () {
+ 'use strict';
+
+ angular
+ .module('traefik.core.provider', ['ngResource'])
+ .factory('Providers', ['$resource', function ($resource) {
+ return $resource('/api/providers');
+ }]);
+
+})();
diff --git a/static/app/sections/health/health.controller.js b/static/app/sections/health/health.controller.js
new file mode 100644
index 000000000..3f2a4ab7c
--- /dev/null
+++ b/static/app/sections/health/health.controller.js
@@ -0,0 +1,26 @@
+(function () {
+ 'use strict';
+
+ angular.module('traefik.section.health')
+ .controller('HealthController', ['$scope', '$interval', '$log', 'Health', function ($scope, $interval, $log, Health) {
+
+ var vm = this;
+
+ vm.health = Health.get();
+
+ var intervalId = $interval(function () {
+ Health.get(function (health) {
+ vm.health = health;
+ }, function (error) {
+ vm.health = {};
+ $log.error(error);
+ });
+ }, 3000);
+
+ $scope.$on('$destroy', function () {
+ $interval.cancel(intervalId);
+ });
+
+ }]);
+
+})();
diff --git a/static/app/sections/health/health.html b/static/app/sections/health/health.html
new file mode 100644
index 000000000..98e50955d
--- /dev/null
+++ b/static/app/sections/health/health.html
@@ -0,0 +1,46 @@
+
+
+ Health
+
+
+ -
+ Average response time sec :{{healthCtrl.health.average_response_time_sec}}
+
+ -
+ Average response time :{{healthCtrl.health.average_response_time}}
+
+ -
+ Total response time sec :{{healthCtrl.health.total_response_time_sec}}
+
+ -
+ Total response time :{{healthCtrl.health.total_response_time}}
+
+ -
+ Total count :{{healthCtrl.health.total_count}}
+
+ -
+ PID :{{healthCtrl.health.pid}}
+
+ -
+ Uptime :{{healthCtrl.health.uptime}}
+
+ -
+ Uptime sec :{{healthCtrl.health.uptime_sec}}
+
+ -
+ Time :{{healthCtrl.health.time}}
+
+ -
+ Unixtime :{{healthCtrl.health.unixtime}}
+
+ -
+ Status code count :{{healthCtrl.health.status_code_count}}
+
+ -
+ Total status code count :{{healthCtrl.health.total_status_code_count}}
+
+ -
+ Count :{{healthCtrl.health.count}}
+
+
+
diff --git a/static/app/sections/health/health.module.js b/static/app/sections/health/health.module.js
new file mode 100644
index 000000000..69a0dd54c
--- /dev/null
+++ b/static/app/sections/health/health.module.js
@@ -0,0 +1,16 @@
+(function () {
+ 'use strict';
+
+ angular.module('traefik.section.health', ['traefik.core.health'])
+ .config(['$stateProvider', function ($stateProvider) {
+
+ $stateProvider.state('health', {
+ url: '/health',
+ templateUrl: 'app/sections/health/health.html',
+ controller: 'HealthController',
+ controllerAs: 'healthCtrl'
+ });
+
+ }]);
+
+})();
diff --git a/static/app/sections/providers/backend-monitor/backend-monitor.controller.js b/static/app/sections/providers/backend-monitor/backend-monitor.controller.js
new file mode 100644
index 000000000..8eab09b35
--- /dev/null
+++ b/static/app/sections/providers/backend-monitor/backend-monitor.controller.js
@@ -0,0 +1,10 @@
+(function () {
+ 'use strict';
+
+ angular
+ .module('traefik.section.providers.backend-monitor')
+ .controller('BackendMonitorController', function () {
+
+ });
+
+})();
diff --git a/static/app/sections/providers/backend-monitor/backend-monitor.directive.js b/static/app/sections/providers/backend-monitor/backend-monitor.directive.js
new file mode 100644
index 000000000..2a2df2515
--- /dev/null
+++ b/static/app/sections/providers/backend-monitor/backend-monitor.directive.js
@@ -0,0 +1,21 @@
+(function () {
+ 'use strict';
+
+ angular
+ .module('traefik.section.providers.backend-monitor')
+ .directive('backendMonitor', function () {
+ return {
+ restrict: 'EA',
+ templateUrl: 'app/sections/providers/backend-monitor/backend-monitor.html',
+ controller: 'BackendMonitorController',
+ controllerAs: 'backendCtrl',
+ bindToController: true,
+ scope: {
+ backend: '=',
+ backendId: '=',
+ providerId: '='
+ }
+ };
+ });
+
+})();
diff --git a/static/app/sections/providers/backend-monitor/backend-monitor.html b/static/app/sections/providers/backend-monitor/backend-monitor.html
new file mode 100644
index 000000000..0d462cc74
--- /dev/null
+++ b/static/app/sections/providers/backend-monitor/backend-monitor.html
@@ -0,0 +1,23 @@
+
+
+ {{backendCtrl.backendId}} [{{backendCtrl.providerId}}]
+
+
+
+
+ Server |
+ URL |
+ Weight |
+
+
+ {{serverId}} |
+ {{server.URL}} |
+ {{server.Weight}} |
+
+
+
+
+
diff --git a/static/app/sections/providers/backend-monitor/backend-monitor.module.js b/static/app/sections/providers/backend-monitor/backend-monitor.module.js
new file mode 100644
index 000000000..ccee5d681
--- /dev/null
+++ b/static/app/sections/providers/backend-monitor/backend-monitor.module.js
@@ -0,0 +1,7 @@
+(function () {
+ 'use strict';
+
+ angular
+ .module('traefik.section.providers.backend-monitor', []);
+
+})();
diff --git a/static/app/sections/providers/frontend-monitor/frontend-monitor.controller.js b/static/app/sections/providers/frontend-monitor/frontend-monitor.controller.js
new file mode 100644
index 000000000..714a47a70
--- /dev/null
+++ b/static/app/sections/providers/frontend-monitor/frontend-monitor.controller.js
@@ -0,0 +1,10 @@
+(function () {
+ 'use strict';
+
+ angular
+ .module('traefik.section.providers.frontend-monitor')
+ .controller('FrontendMonitorController', function () {
+
+ });
+
+})();
diff --git a/static/app/sections/providers/frontend-monitor/frontend-monitor.directive.js b/static/app/sections/providers/frontend-monitor/frontend-monitor.directive.js
new file mode 100644
index 000000000..ed0ae4998
--- /dev/null
+++ b/static/app/sections/providers/frontend-monitor/frontend-monitor.directive.js
@@ -0,0 +1,21 @@
+(function () {
+ 'use strict';
+
+ angular
+ .module('traefik.section.providers.frontend-monitor')
+ .directive('frontendMonitor', function () {
+ return {
+ restrict: 'EA',
+ templateUrl: 'app/sections/providers/frontend-monitor/frontend-monitor.html',
+ controller: 'FrontendMonitorController',
+ controllerAs: 'frontendCtrl',
+ bindToController: true,
+ scope: {
+ frontend: '=',
+ frontendId: '=',
+ providerId: '='
+ }
+ };
+ });
+
+})();
diff --git a/static/app/sections/providers/frontend-monitor/frontend-monitor.html b/static/app/sections/providers/frontend-monitor/frontend-monitor.html
new file mode 100644
index 000000000..08f226d41
--- /dev/null
+++ b/static/app/sections/providers/frontend-monitor/frontend-monitor.html
@@ -0,0 +1,22 @@
+
+
+ {{frontendCtrl.frontendId}} [{{frontendCtrl.providerId}}]
+
+
+
+
+ Route |
+ Rule |
+ Value |
+
+
+ {{routeId}} |
+ {{route.Rule}} |
+ {{route.Value}} |
+
+
+
+
+
diff --git a/static/app/sections/providers/frontend-monitor/frontend-monitor.module.js b/static/app/sections/providers/frontend-monitor/frontend-monitor.module.js
new file mode 100644
index 000000000..6257a7768
--- /dev/null
+++ b/static/app/sections/providers/frontend-monitor/frontend-monitor.module.js
@@ -0,0 +1,6 @@
+(function () {
+ 'use strict';
+
+ angular.module('traefik.section.providers.frontend-monitor', []);
+
+})();
diff --git a/static/app/sections/providers/providers.controller.js b/static/app/sections/providers/providers.controller.js
new file mode 100644
index 000000000..92b717053
--- /dev/null
+++ b/static/app/sections/providers/providers.controller.js
@@ -0,0 +1,27 @@
+(function () {
+ 'use strict';
+
+ angular
+ .module('traefik.section.providers')
+ .controller('ProvidersController', ['$scope', '$interval', '$log', 'Providers', function ($scope, $interval, $log, Providers) {
+
+ var vm = this;
+
+ vm.providers = Providers.get();
+
+ var intervalId = $interval(function () {
+ Providers.get(function (providers) {
+ vm.providers = providers;
+ }, function (error) {
+ vm.providers = {};
+ $log.error(error);
+ });
+ }, 2000);
+
+ $scope.$on('$destroy', function () {
+ $interval.cancel(intervalId);
+ });
+
+ }]);
+
+})();
diff --git a/static/app/sections/providers/providers.html b/static/app/sections/providers/providers.html
new file mode 100644
index 000000000..5db7daa10
--- /dev/null
+++ b/static/app/sections/providers/providers.html
@@ -0,0 +1,14 @@
+
+
diff --git a/static/app/sections/providers/providers.module.js b/static/app/sections/providers/providers.module.js
new file mode 100644
index 000000000..92091036a
--- /dev/null
+++ b/static/app/sections/providers/providers.module.js
@@ -0,0 +1,21 @@
+(function () {
+ 'use strict';
+
+ angular
+ .module('traefik.section.providers', [
+ 'traefik.core.provider',
+ 'traefik.section.providers.backend-monitor',
+ 'traefik.section.providers.frontend-monitor'
+ ])
+ .config(['$stateProvider', function ($stateProvider) {
+
+ $stateProvider.state('provider', {
+ url: '/',
+ templateUrl: 'app/sections/providers/providers.html',
+ controller: 'ProvidersController',
+ controllerAs: 'providersCtrl'
+ });
+
+ }]);
+
+})();
diff --git a/static/app/sections/sections.config.js b/static/app/sections/sections.config.js
new file mode 100644
index 000000000..21464b747
--- /dev/null
+++ b/static/app/sections/sections.config.js
@@ -0,0 +1,12 @@
+(function () {
+ 'use strict';
+
+ angular
+ .module('traefik.section')
+ .config(['$urlRouterProvider', function ($urlRouterProvider) {
+
+ $urlRouterProvider.otherwise('/');
+
+ }]);
+
+})();
diff --git a/static/app/sections/sections.module.js b/static/app/sections/sections.module.js
new file mode 100644
index 000000000..98e3e66e2
--- /dev/null
+++ b/static/app/sections/sections.module.js
@@ -0,0 +1,11 @@
+(function () {
+ 'use strict';
+
+ angular
+ .module('traefik.section', [
+ 'ui.router',
+ 'traefik.section.providers',
+ 'traefik.section.health'
+ ]);
+
+})();
diff --git a/static/app/traefik.js b/static/app/traefik.js
new file mode 100644
index 000000000..ca961c933
--- /dev/null
+++ b/static/app/traefik.js
@@ -0,0 +1,6 @@
+(function () {
+ 'use strict';
+
+ angular.module('traefik', ['traefik.section']);
+
+})();
diff --git a/static/fonts/charter_regular-webfont.eot b/static/fonts/charter_regular-webfont.eot
new file mode 100644
index 000000000..01872e348
Binary files /dev/null and b/static/fonts/charter_regular-webfont.eot differ
diff --git a/static/fonts/charter_regular-webfont.ttf b/static/fonts/charter_regular-webfont.ttf
new file mode 100644
index 000000000..44e097ada
Binary files /dev/null and b/static/fonts/charter_regular-webfont.ttf differ
diff --git a/static/fonts/charter_regular-webfont.woff b/static/fonts/charter_regular-webfont.woff
new file mode 100644
index 000000000..a19483d01
Binary files /dev/null and b/static/fonts/charter_regular-webfont.woff differ
diff --git a/static/index.html b/static/index.html
new file mode 100644
index 000000000..632ce2225
--- /dev/null
+++ b/static/index.html
@@ -0,0 +1,79 @@
+
+
+
+
+
+
+
+ /ˈTræfɪk/
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/static/style.css b/static/style.css
new file mode 100644
index 000000000..ad4fed7c4
--- /dev/null
+++ b/static/style.css
@@ -0,0 +1,22 @@
+
+@font-face {
+ font-family: 'charterregular';
+ src: url('fontss/charter_regular-webfont.eot');
+ src: url('fontss/charter_regular-webfont.eot?#iefix') format('embedded-opentype'),
+ url('fontss/charter_regular-webfont.woff') format('woff');
+ font-weight: normal;
+ font-style: normal;
+}
+
+.traefik-blue {
+ color: #00B1FF;
+}
+
+.traefik-text {
+ font-family: 'WebFont', Arial, sans-serif;
+}
+
+.panel-body .panel-table__servers,
+.panel-body .panel-table__routes {
+ margin-bottom: 0;
+}