Index: /branches/HiveStatistics/sources/HeuristicLab.Services.WebApp.Status/3.3/HeuristicLab.Services.WebApp.Status-3.3.csproj
===================================================================
--- /branches/HiveStatistics/sources/HeuristicLab.Services.WebApp.Status/3.3/HeuristicLab.Services.WebApp.Status-3.3.csproj	(revision 12557)
+++ /branches/HiveStatistics/sources/HeuristicLab.Services.WebApp.Status/3.3/HeuristicLab.Services.WebApp.Status-3.3.csproj	(revision 12558)
@@ -76,4 +76,5 @@
       <SpecificVersion>False</SpecificVersion>
       <HintPath>..\..\packages\Newtonsoft.Json.7.0.1\lib\net45\Newtonsoft.Json.dll</HintPath>
+      <Private>False</Private>
     </Reference>
     <Reference Include="System" />
Index: /branches/HiveStatistics/sources/HeuristicLab.Services.WebApp.Status/3.3/WebApi/DataController.cs
===================================================================
--- /branches/HiveStatistics/sources/HeuristicLab.Services.WebApp.Status/3.3/WebApi/DataController.cs	(revision 12557)
+++ /branches/HiveStatistics/sources/HeuristicLab.Services.WebApp.Status/3.3/WebApi/DataController.cs	(revision 12558)
@@ -216,5 +216,4 @@
       double mean = 0;
       double M2 = 0;
-
       foreach (double x in source) {
         n = n + 1;
Index: /branches/HiveStatistics/sources/HeuristicLab.Services.WebApp.Status/3.3/WebApp/status/status.cshtml
===================================================================
--- /branches/HiveStatistics/sources/HeuristicLab.Services.WebApp.Status/3.3/WebApp/status/status.cshtml	(revision 12557)
+++ /branches/HiveStatistics/sources/HeuristicLab.Services.WebApp.Status/3.3/WebApp/status/status.cshtml	(revision 12558)
@@ -216,22 +216,24 @@
             </div>
             <div class="panel-body">
-                <table class="table table-hover">
+                <table class="table table-hover" ts-wrapper>
                     <thead>
-                    <tr>
-                        <th>Username</th>
-                        <th>Calculating Tasks</th>
-                        <th>Waiting Tasks</th>
-                    </tr>
+                        <tr>
+                            <th ts-criteria="User.Name">Username</th>
+                            <th ts-criteria="CalculatingTasks|parseInt">Calculating Tasks</th>
+                            <th ts-criteria="WaitingTasks|parseInt">Waiting Tasks</th>
+                        </tr>
                     </thead>
-                    <tr ng-repeat="task in status.TasksStatus">
-                        <td>{{task.User.Name}}</td>
-                        <td>{{task.CalculatingTasks | number}}</td>
-                        <td>{{task.WaitingTasks | number}}</td>
-                    </tr>
-                    <tr ng-hide="status.TasksStatus.length">
-                        <td colspan="3" class="text-center">
-                            There are no waiting or calculating tasks available!
-                        </td>
-                    </tr>
+                    <tbody>
+                        <tr ng-repeat="task in status.TasksStatus" ts-repeat>
+                            <td>{{task.User.Name}}</td>
+                            <td>{{task.CalculatingTasks | number}}</td>
+                            <td>{{task.WaitingTasks | number}}</td>
+                        </tr>
+                        <tr ng-hide="status.TasksStatus.length">
+                            <td colspan="3" class="text-center">
+                                There are no waiting or calculating tasks available!
+                            </td>
+                        </tr>
+                    </tbody>
                 </table>
             </div>
@@ -254,41 +256,30 @@
                  class="panel-collapse collapse in">
                 <div class="panel-body">
-                    <table class="table table-hover">
+                    <table class="table table-hover" ts-wrapper>
                         <thead>
-                        <tr>
-                            <th ng-click="activeCalculatingSlavesOrderColumn='Slave.Name';
-                                                  activeCalculatingSlavesReverseSort=!activeCalculatingSlavesReverseSort">
-                                Slave
-                            </th>
-                            <th ng-click="activeCalculatingSlavesOrderColumn='CpuUtilization';
-                                                  activeCalculatingSlavesReverseSort=!activeCalculatingSlavesReverseSort">
-                                CPU Utilization
-                            </th>
-                            <th ng-click="activeCalculatingSlavesOrderColumn='Cores';
-                                                  activeCalculatingSlavesReverseSort=!activeCalculatingSlavesReverseSort">
-                                Cores
-                            </th>
-                            <th ng-click="activeCalculatingSlavesOrderColumn='Memory';
-                                                  activeCalculatingSlavesReverseSort=!activeCalculatingSlavesReverseSort">
-                                Memory
-                            </th>
-                        </tr>
+                            <tr>
+                                <th ts-criteria="Slave.Name">Slave</th>
+                                <th ts-criteria="CpuUtilization|parseFloat">CPU Utilization</th>
+                                <th ts-criteria="Cores|parseInt">Cores</th>
+                                <th ts-criteria="Memory|parseInt">Memory</th>
+                            </tr>
                         </thead>
-                        <tr ng-repeat="slave in activeCalculatingSlaves = (status.SlavesStatus
+                        <tbody>
+                            <tr ng-repeat="slave in activeCalculatingSlaves = (status.SlavesStatus
                                 | filter: {
                                     IsAllowedToCalculate: true,
                                     State: 'Calculating'
-                                  }
-                                | orderBy: activeCalculatingSlavesOrderColumn:activeCalculatingSlavesReverseSort)">
-                            <td>{{slave.Slave.Name}}</td>
-                            <td>{{slave.CpuUtilization | number: 2}} %</td>
-                            <td>{{slave.Cores - slave.FreeCores | number}} / {{slave.Cores | number}}</td>
-                            <td>{{slave.Memory - slave.FreeMemory | kbToGB}} / {{slave.Memory | kbToGB}} GB</td>
-                        </tr>
-                        <tr ng-hide="activeCalculatingSlaves.length">
-                            <td colspan="4" class="text-center">
-                                There are no active calculating slaves available!
-                            </td>
-                        </tr>
+                                  })" ts-repeat>
+                                <td>{{slave.Slave.Name}}</td>
+                                <td>{{slave.CpuUtilization | number: 2}} %</td>
+                                <td>{{slave.Cores - slave.FreeCores | number}} / {{slave.Cores | number}}</td>
+                                <td>{{slave.Memory - slave.FreeMemory | kbToGB}} / {{slave.Memory | kbToGB}} GB</td>
+                            </tr>
+                            <tr ng-hide="activeCalculatingSlaves.length">
+                                <td colspan="4" class="text-center">
+                                    There are no active calculating slaves available!
+                                </td>
+                            </tr>
+                        </tbody>
                     </table>
                 </div>
@@ -312,41 +303,30 @@
                  class="panel-collapse collapse">
                 <div class="panel-body">
-                    <table class="table table-hover">
+                    <table class="table table-hover" ts-wrapper>
                         <thead>
                         <tr>
-                            <th ng-click="activeIdleSlavesOrderColumn='Slave.Name';
-                                                  activeIdleSlavesReverseSort=!activeIdleSlavesReverseSort">
-                                Slave
-                            </th>
-                            <th ng-click="activeIdleSlavesOrderColumn='CpuUtilization';
-                                                  activeIdleSlavesReverseSort=!activeIdleSlavesReverseSort">
-                                CPU Utilization
-                            </th>
-                            <th ng-click="activeIdleSlavesOrderColumn='Cores';
-                                                  activeIdleSlavesReverseSort=!activeIdleSlavesReverseSort">
-                                Cores
-                            </th>
-                            <th ng-click="activeIdleSlavesOrderColumn='Memory';
-                                                  activeIdleSlavesReverseSort=!activeIdleSlavesReverseSort">
-                                Memory
-                            </th>
+                            <th ts-criteria="Slave.Name">Slave</th>
+                            <th ts-criteria="CpuUtilization|parseFloat">CPU Utilization</th>
+                            <th ts-criteria="Cores|parseInt">Cores</th>
+                            <th ts-criteria="Memory|parseInt">Memory</th>
                         </tr>
                         </thead>
-                        <tr ng-repeat="slave in activeIdleSlaves = (status.SlavesStatus
+                        <tbody>
+                            <tr ng-repeat="slave in activeIdleSlaves = (status.SlavesStatus
                                 | filter: {
                                     IsAllowedToCalculate: true,
                                     State: 'Idle'
-                                  }
-                                | orderBy: activeIdleSlavesOrderColumn:activeIdleSlavesReverseSort)">
-                            <td>{{slave.Slave.Name}}</td>
-                            <td>{{slave.CpuUtilization | number: 2}} %</td>
-                            <td>{{slave.Cores - slave.FreeCores | number}} / {{slave.Cores | number}}</td>
-                            <td>{{slave.Memory - slave.FreeMemory | kbToGB}} / {{slave.Memory | kbToGB}} GB</td>
-                        </tr>
-                        <tr ng-hide="activeIdleSlaves.length">
-                            <td colspan="4" class="text-center">
-                            There are no active idle slaves available!
-                            <td>
-                        </tr>
+                                  })" ts-repeat>
+                                <td>{{slave.Slave.Name}}</td>
+                                <td>{{slave.CpuUtilization | number: 2}} %</td>
+                                <td>{{slave.Cores - slave.FreeCores | number}} / {{slave.Cores | number}}</td>
+                                <td>{{slave.Memory - slave.FreeMemory | kbToGB}} / {{slave.Memory | kbToGB}} GB</td>
+                            </tr>
+                            <tr ng-hide="activeIdleSlaves.length">
+                                <td colspan="4" class="text-center">
+                                    There are no active idle slaves available!
+                                <td>
+                            </tr>
+                        </tbody>
                     </table>
                 </div>
@@ -370,38 +350,27 @@
                  class="panel-collapse collapse">
                 <div class="panel-body">
-                    <table class="table table-hover">
+                    <table class="table table-hover" ts-wrapper>
                         <thead>
-                        <tr>
-                            <th ng-click="inactiveSlavesOrderColumn='Slave.Name';
-                                                  inactiveSlavesReverseSort=!inactiveSlavesReverseSort">
-                                Slave
-                            </th>
-                            <th ng-click="inactiveSlavesOrderColumn='CpuUtilization';
-                                                  inactiveSlavesReverseSort=!inactiveSlavesReverseSort">
-                                CPU Utilization
-                            </th>
-                            <th ng-click="inactiveSlavesOrderColumn='Cores';
-                                                  inactiveSlavesReverseSort=!inactiveSlavesReverseSort">
-                                Cores
-                            </th>
-                            <th ng-click="inactiveSlavesOrderColumn='Memory';
-                                                  inactiveSlavesReverseSort=!inactiveSlavesReverseSort">
-                                Memory
-                            </th>
-                        </tr>
+                            <tr>
+                                <th ts-criteria="Slave.Name">Slave</th>
+                                <th ts-criteria="CpuUtilization|parseFloat">CPU Utilization</th>
+                                <th ts-criteria="Cores|parseInt">Cores</th>
+                                <th ts-criteria="Memory|parseInt">Memory</th>
+                            </tr>
                         </thead>
-                        <tr ng-repeat="slave in inactiveSlaves = (status.SlavesStatus
+                        <tbody>
+                            <tr ng-repeat="slave in inactiveSlaves = (status.SlavesStatus
                                 | filter: {
                                     IsAllowedToCalculate: false
-                                  }
-                                | orderBy: inactiveSlavesOrderColumn:inactiveSlavesReverseSort)">
-                            <td>{{slave.Slave.Name}}</td>
-                            <td>{{slave.CpuUtilization | number: 2}} %</td>
-                            <td>{{slave.Cores - slave.FreeCores | number}} / {{slave.Cores | number}}</td>
-                            <td>{{slave.Memory - slave.FreeMemory | kbToGB}} / {{slave.Memory | kbToGB}} GB</td>
-                        </tr>
-                        <tr ng-hide="inactiveSlaves.length">
-                            <td colspan="4" class="text-center">No inactive slaves available!</td>
-                        </tr>
+                                  })" ts-repeat>
+                                <td>{{slave.Slave.Name}}</td>
+                                <td>{{slave.CpuUtilization | number: 2}} %</td>
+                                <td>{{slave.Cores - slave.FreeCores | number}} / {{slave.Cores | number}}</td>
+                                <td>{{slave.Memory - slave.FreeMemory | kbToGB}} / {{slave.Memory | kbToGB}} GB</td>
+                            </tr>
+                            <tr ng-hide="inactiveSlaves.length">
+                                <td colspan="4" class="text-center">No inactive slaves available!</td>
+                            </tr>
+                        </tbody>
                     </table>
                 </div>
Index: /branches/HiveStatistics/sources/HeuristicLab.Services.WebApp.Status/3.3/WebApp/status/statusCtrl.js
===================================================================
--- /branches/HiveStatistics/sources/HeuristicLab.Services.WebApp.Status/3.3/WebApp/status/statusCtrl.js	(revision 12557)
+++ /branches/HiveStatistics/sources/HeuristicLab.Services.WebApp.Status/3.3/WebApp/status/statusCtrl.js	(revision 12558)
@@ -84,18 +84,4 @@
                 CalculatingTasks: 0
             };
-
-            $scope.activeIdleSlaveFilter = function (slave) {
-                return (slave.IsAllowedToCalculate == true) && (slave.State == 'Idle');
-            };
-
-            $scope.activeCalculatingSlavesReverseSort = false;
-            $scope.activeCalculatingSlavesOrderColumn = 'slave.Slave.Name';
-
-            $scope.activeIdleSlavesReverseSort = false;
-            $scope.activeIdleSlavesOrderColumn = 'slave.Slave.Name';
-
-            $scope.inactiveSlavesReverseSort = false;
-            $scope.inactiveSlavesOrderColumn = 'slave.Slave.Name';
-
 
             var updateStatus = function () {
Index: /branches/HiveStatistics/sources/HeuristicLab.Services.WebApp.Status/3.3/status.js
===================================================================
--- /branches/HiveStatistics/sources/HeuristicLab.Services.WebApp.Status/3.3/status.js	(revision 12557)
+++ /branches/HiveStatistics/sources/HeuristicLab.Services.WebApp.Status/3.3/status.js	(revision 12558)
@@ -2,5 +2,5 @@
 (function () {
     var plugin = appStatusPlugin;
-    plugin.dependencies = ['ngResource', 'ui.knob', 'ui.bootstrap'];
+    plugin.dependencies = ['ngResource', 'ui.knob', 'ui.bootstrap', 'tableSort'];
     plugin.files = [
         'WebApp/status.css',
@@ -15,5 +15,5 @@
     ];
     var menu = app.getMenu();
-    var section = menu.getSection('Menü', 1);
+    var section = menu.getSection('Menu', 1);
     section.addEntry({
         name: 'Status',
Index: /branches/HiveStatistics/sources/HeuristicLab.Services.WebApp/3.3/Configs/BundleConfig.cs
===================================================================
--- /branches/HiveStatistics/sources/HeuristicLab.Services.WebApp/3.3/Configs/BundleConfig.cs	(revision 12557)
+++ /branches/HiveStatistics/sources/HeuristicLab.Services.WebApp/3.3/Configs/BundleConfig.cs	(revision 12558)
@@ -41,5 +41,6 @@
         "~/WebApp/libs/bootstrap/css/bootstrap-theme.min.css",
         "~/WebApp/libs/font-aweseome/font-aweseome.min.css",
-        "~/WebApp/libs/angularjs/loading-bar/loading-bar.css"
+        "~/WebApp/libs/angularjs/loading-bar/loading-bar.css",
+        "~/WebApp/libs/angularjs/angular-tablesort/tablesort.css"
       ));
 
@@ -70,4 +71,5 @@
         "~/WebApp/libs/angularjs/angular-ui-router.min.js",
         "~/WebApp/libs/angularjs/angular-knob/angular-knob.js",
+        "~/WebApp/libs/angularjs/angular-tablesort/angular-tablesort.js",
         "~/WebApp/libs/angularjs/angular-ui/ui-bootstrap-tpls-0.13.0.min.js",
         "~/WebApp/libs/angularjs/loading-bar/loading-bar.js",
Index: /branches/HiveStatistics/sources/HeuristicLab.Services.WebApp/3.3/Controllers/AppController.cs
===================================================================
--- /branches/HiveStatistics/sources/HeuristicLab.Services.WebApp/3.3/Controllers/AppController.cs	(revision 12557)
+++ /branches/HiveStatistics/sources/HeuristicLab.Services.WebApp/3.3/Controllers/AppController.cs	(revision 12558)
@@ -47,4 +47,7 @@
     }
 
+    public ActionResult RedirectUrl(string url) {
+      return RedirectPermanent(url);
+    }
   }
 }
Index: /branches/HiveStatistics/sources/HeuristicLab.Services.WebApp/3.3/HeuristicLab.Services.WebApp-3.3.csproj
===================================================================
--- /branches/HiveStatistics/sources/HeuristicLab.Services.WebApp/3.3/HeuristicLab.Services.WebApp-3.3.csproj	(revision 12557)
+++ /branches/HiveStatistics/sources/HeuristicLab.Services.WebApp/3.3/HeuristicLab.Services.WebApp-3.3.csproj	(revision 12558)
@@ -143,4 +143,6 @@
     <Content Include="WebApp\app.css" />
     <Content Include="Global.asax" />
+    <Content Include="WebApp\libs\angularjs\angular-tablesort\angular-tablesort.js" />
+    <Content Include="WebApp\libs\angularjs\angular-tablesort\tablesort.css" />
     <Content Include="WebApp\libs\angularjs\fittext\ng-FitText.js" />
     <Content Include="WebApp\main.js" />
Index: /branches/HiveStatistics/sources/HeuristicLab.Services.WebApp/3.3/WebApp/libs/angularjs/angular-tablesort/angular-tablesort.js
===================================================================
--- /branches/HiveStatistics/sources/HeuristicLab.Services.WebApp/3.3/WebApp/libs/angularjs/angular-tablesort/angular-tablesort.js	(revision 12558)
+++ /branches/HiveStatistics/sources/HeuristicLab.Services.WebApp/3.3/WebApp/libs/angularjs/angular-tablesort/angular-tablesort.js	(revision 12558)
@@ -0,0 +1,222 @@
+﻿/*
+ angular-tablesort v1.0.7
+ (c) 2013-2015 Mattias Holmlund, http://mattiash.github.io/angular-tablesort
+ License: MIT
+*/
+
+var tableSortModule = angular.module('tableSort', []);
+
+tableSortModule.directive('tsWrapper', ['$log', '$parse', function ($log, $parse) {
+    'use strict';
+    return {
+        scope: true,
+        controller: ['$scope', function ($scope) {
+            $scope.sortExpression = [];
+            $scope.headings = [];
+
+            var parse_sortexpr = function (expr) {
+                return [$parse(expr), null, false];
+            };
+
+            this.setSortField = function (sortexpr, element) {
+                var i;
+                var expr = parse_sortexpr(sortexpr);
+                if ($scope.sortExpression.length === 1
+                    && $scope.sortExpression[0][0] === expr[0]) {
+                    if ($scope.sortExpression[0][2]) {
+                        element.removeClass("tablesort-desc");
+                        element.addClass("tablesort-asc");
+                        $scope.sortExpression[0][2] = false;
+                    }
+                    else {
+                        element.removeClass("tablesort-asc");
+                        element.addClass("tablesort-desc");
+                        $scope.sortExpression[0][2] = true;
+                    }
+                }
+                else {
+                    for (i = 0; i < $scope.headings.length; i = i + 1) {
+                        $scope.headings[i]
+                            .removeClass("tablesort-desc")
+                            .removeClass("tablesort-asc");
+                    }
+                    element.addClass("tablesort-asc");
+                    $scope.sortExpression = [expr];
+                }
+            };
+
+            this.addSortField = function (sortexpr, element) {
+                var i;
+                var toggle_order = false;
+                var expr = parse_sortexpr(sortexpr);
+                for (i = 0; i < $scope.sortExpression.length; i = i + 1) {
+                    if ($scope.sortExpression[i][0] === expr[0]) {
+                        if ($scope.sortExpression[i][2]) {
+                            element.removeClass("tablesort-desc");
+                            element.addClass("tablesort-asc");
+                            $scope.sortExpression[i][2] = false;
+                        }
+                        else {
+                            element.removeClass("tablesort-asc");
+                            element.addClass("tablesort-desc");
+                            $scope.sortExpression[i][2] = true;
+                        }
+                        toggle_order = true;
+                    }
+                }
+                if (!toggle_order) {
+                    element.addClass("tablesort-asc");
+                    $scope.sortExpression.push(expr);
+                }
+            };
+
+            this.setTrackBy = function (trackBy) {
+                $scope.trackBy = trackBy;
+            };
+
+            this.registerHeading = function (headingelement) {
+                $scope.headings.push(headingelement);
+            };
+
+            $scope.sortFun = function (a, b) {
+                var i, aval, bval, descending, filterFun;
+                for (i = 0; i < $scope.sortExpression.length; i = i + 1) {
+                    aval = $scope.sortExpression[i][0](a);
+                    bval = $scope.sortExpression[i][0](b);
+                    filterFun = b[$scope.sortExpression[i][1]];
+                    if (filterFun) {
+                        aval = filterFun(aval);
+                        bval = filterFun(bval);
+                    }
+                    if (aval === undefined || aval === null) {
+                        aval = "";
+                    }
+                    if (bval === undefined || bval === null) {
+                        bval = "";
+                    }
+                    descending = $scope.sortExpression[i][2];
+                    if (aval > bval) {
+                        return descending ? -1 : 1;
+                    }
+                    else if (aval < bval) {
+                        return descending ? 1 : -1;
+                    }
+                }
+
+                // All the sort fields were equal. If there is a "track by" expression,
+                // use that as a tiebreaker to make the sort result stable.
+                if ($scope.trackBy) {
+                    aval = a[$scope.trackBy];
+                    bval = b[$scope.trackBy];
+                    if (aval === undefined || aval === null) {
+                        aval = "";
+                    }
+                    if (bval === undefined || bval === null) {
+                        bval = "";
+                    }
+                    if (aval > bval) {
+                        return descending ? -1 : 1;
+                    }
+                    else if (aval < bval) {
+                        return descending ? 1 : -1;
+                    }
+                }
+                return 0;
+            };
+        }]
+    };
+}]);
+
+tableSortModule.directive('tsCriteria', function () {
+    return {
+        require: "^tsWrapper",
+        link: function (scope, element, attrs, tsWrapperCtrl) {
+            var clickingCallback = function (event) {
+                scope.$apply(function () {
+                    if (event.shiftKey) {
+                        tsWrapperCtrl.addSortField(attrs.tsCriteria, element);
+                    }
+                    else {
+                        tsWrapperCtrl.setSortField(attrs.tsCriteria, element);
+                    }
+                });
+            };
+            element.bind('click', clickingCallback);
+            element.addClass('tablesort-sortable');
+            if ("tsDefault" in attrs && attrs.tsDefault !== "0") {
+                tsWrapperCtrl.addSortField(attrs.tsCriteria, element);
+                if (attrs.tsDefault == "descending") {
+                    tsWrapperCtrl.addSortField(attrs.tsCriteria, element);
+                }
+            }
+            tsWrapperCtrl.registerHeading(element);
+        }
+    };
+});
+
+tableSortModule.directive("tsRepeat", ['$compile', function ($compile) {
+    return {
+        terminal: true,
+        require: "^tsWrapper",
+        priority: 1000000,
+        link: function (scope, element, attrs, tsWrapperCtrl) {
+            var clone = element.clone();
+            var tdcount = element[0].childElementCount;
+            var ngRepeatDirective = "ng-repeat";
+            if (typeof (clone.attr(ngRepeatDirective)) === "undefined") {
+                ngRepeatDirective = "data-ng-repeat";
+            }
+            var repeatExpr = clone.attr(ngRepeatDirective);
+            var trackBy = null;
+            var trackByMatch = repeatExpr.match(/\s+track\s+by\s+\S+?\.(\S+)/);
+            if (trackByMatch) {
+                trackBy = trackByMatch[1];
+                tsWrapperCtrl.setTrackBy(trackBy);
+            }
+
+            if (repeatExpr.search(/tablesort/) != -1) {
+                repeatExpr = repeatExpr.replace(/tablesort/, "tablesortOrderBy:sortFun");
+            } else {
+                repeatExpr = repeatExpr.replace(/^\s*([\s\S]+?)\s+in\s+([\s\S]+?)(\s+track\s+by\s+[\s\S]+?)?\s*$/,
+                    "$1 in $2 | tablesortOrderBy:sortFun$3");
+            }
+
+
+
+            while (element[0].firstChild) {
+                element[0].removeChild(element[0].firstChild);
+            }
+            var td = document.createElement("td");
+            td.colSpan = tdcount;
+            element[0].appendChild(td);
+
+            element[0].className += " showIfLast";
+            clone.removeAttr("ts-repeat");
+
+            clone.attr(ngRepeatDirective, repeatExpr);
+            var clonedElement = $compile(clone)(scope);
+            element.after(clonedElement);
+        }
+    };
+}]);
+
+tableSortModule.filter('tablesortOrderBy', function () {
+    return function (array, sortfun) {
+        if (!array) return;
+        var arrayCopy = [];
+        for (var i = 0; i < array.length; i++) { arrayCopy.push(array[i]); }
+        return arrayCopy.sort(sortfun);
+    };
+});
+
+tableSortModule.filter('parseInt', function () {
+    return function (input) {
+        return parseInt(input) || null;
+    };
+});
+
+tableSortModule.filter('parseFloat', function () {
+    return function (input) {
+        return parseFloat(input) || null;
+    };
+});
Index: /branches/HiveStatistics/sources/HeuristicLab.Services.WebApp/3.3/WebApp/libs/angularjs/angular-tablesort/tablesort.css
===================================================================
--- /branches/HiveStatistics/sources/HeuristicLab.Services.WebApp/3.3/WebApp/libs/angularjs/angular-tablesort/tablesort.css	(revision 12558)
+++ /branches/HiveStatistics/sources/HeuristicLab.Services.WebApp/3.3/WebApp/libs/angularjs/angular-tablesort/tablesort.css	(revision 12558)
@@ -0,0 +1,56 @@
+﻿th.tablesort-sortable {
+    -webkit-user-select: none;
+    -khtml-user-select: none;
+    -moz-user-select: none;
+    -o-user-select: none;
+    user-select: none;
+    cursor: pointer;
+}
+
+table .tablesort-sortable:after{
+    content:"";
+    float:right;
+    margin-top:7px;
+    visibility:hidden;
+    border-left:4px solid transparent;
+    border-right:4px solid transparent;
+
+    border-top:none;
+    border-bottom:4px solid #000;
+}
+
+table .tablesort-desc:after{
+    border-top:4px solid #000;
+    border-bottom:none;
+}
+
+table .tablesort-asc,table .tablesort-desc {
+    background-color: transparent;
+}
+
+table .tablesort-sortable:hover:after, table .tablesort-asc:after, table .tablesort-desc:after {
+    visibility:visible;
+}
+
+/*
+ * Styling for the table row shown in empty tables
+ */
+
+/* The row is always added as the first row in a table
+   Hide it by default */
+.showIfLast {
+    display: none;
+}
+
+/* Only show it if it is also the last row of the table. */
+.showIfLast:last-child {
+    display: table-row;
+}
+
+.showIfLast td {
+    text-align: center;
+}
+
+.showIfLast td:after {
+    content: "No data";
+}
Index: /branches/HiveStatistics/sources/HeuristicLab.Services.WebApp/3.3/WebApp/plugins/login/loginCtrl.js
===================================================================
--- /branches/HiveStatistics/sources/HeuristicLab.Services.WebApp/3.3/WebApp/plugins/login/loginCtrl.js	(revision 12557)
+++ /branches/HiveStatistics/sources/HeuristicLab.Services.WebApp/3.3/WebApp/plugins/login/loginCtrl.js	(revision 12558)
@@ -9,5 +9,5 @@
                         $window.location.reload();
                     } else {
-                        $scope.result = "error logging in";
+                        $scope.result = "Invalid username or password. Please try again.";
                     }
                 });
Index: /branches/HiveStatistics/sources/HeuristicLab.Services.WebApp/3.3/WebApp/plugins/plugins/plugins.cshtml
===================================================================
--- /branches/HiveStatistics/sources/HeuristicLab.Services.WebApp/3.3/WebApp/plugins/plugins/plugins.cshtml	(revision 12557)
+++ /branches/HiveStatistics/sources/HeuristicLab.Services.WebApp/3.3/WebApp/plugins/plugins/plugins.cshtml	(revision 12558)
@@ -16,29 +16,31 @@
                 </div>
                 <div class="panel-body">
-                    <table class="table table-hover table-condensed">
+                    <table class="table table-hover table-condensed" ts-wrapper>
                         <thead>
                             <tr>
                                 <th>#</th>
-                                <th>Name</th>
-                                <th>Assembly</th>
-                                <th>Last reload</th>
+                                <th ts-criteria="Name">Name</th>
+                                <th ts-criteria="AssemblyName">Assembly</th>
+                                <th ts-criteria="LastReload">Last reload</th>
                                 <th>Status</th>
                                 <th></th>
                             </tr>
                         </thead>
-                        <tr ng-repeat="plugin in plugins">
-                            <td>{{$index + 1}}</td>
-                            <td>{{plugin.Name}}</td>
-                            <td>{{plugin.AssemblyName}}</td>
-                            <td>{{plugin.LastReload}}</td>
-                            <td>
-                                <span ng-hide="plugin.Exception" class="glyphicon glyphicon glyphicon-ok" style="color: green"></span>
-                                <span ng-show="plugin.Exception" class="glyphicon glyphicon glyphicon-remove" style="color: darkred"
-                                      ng-click="open(plugin.Name, plugin.Exception)"></span>
-                            </td>
-                            <td>
-                                <a ng-href="" class="cursor-pointer" data-ng-click="reloadPlugin(plugin.Name)">Reload</a>
-                            </td>
-                        </tr>
+                        <tbody>
+                            <tr ng-repeat="plugin in plugins" ts-repeat>
+                                <td>{{$index + 1}}</td>
+                                <td>{{plugin.Name}}</td>
+                                <td>{{plugin.AssemblyName}}</td>
+                                <td>{{plugin.LastReload}}</td>
+                                <td>
+                                    <span ng-hide="plugin.Exception" class="glyphicon glyphicon glyphicon-ok" style="color: green"></span>
+                                    <span ng-show="plugin.Exception" class="glyphicon glyphicon glyphicon-remove" style="color: darkred"
+                                          ng-click="open(plugin.Name, plugin.Exception)"></span>
+                                </td>
+                                <td>
+                                    <a ng-href="" class="cursor-pointer" data-ng-click="reloadPlugin(plugin.Name)">Reload</a>
+                                </td>
+                            </tr>
+                        </tbody>
                     </table>
                 </div>
Index: /branches/HiveStatistics/sources/HeuristicLab.Services.WebApp/3.3/WebApp/plugins/plugins/plugins.js
===================================================================
--- /branches/HiveStatistics/sources/HeuristicLab.Services.WebApp/3.3/WebApp/plugins/plugins/plugins.js	(revision 12557)
+++ /branches/HiveStatistics/sources/HeuristicLab.Services.WebApp/3.3/WebApp/plugins/plugins/plugins.js	(revision 12558)
@@ -2,5 +2,5 @@
 (function () {
     var plugin = appPluginsPlugin;
-    plugin.dependencies = ['ngResource', 'ui.bootstrap'];
+    plugin.dependencies = ['ngResource', 'ui.bootstrap', 'tableSort'];
     plugin.files = [
         'pluginsService.js',
