Free cookie consent management tool by TermsFeed Policy Generator

Ignore:
Timestamp:
06/30/15 13:12:07 (9 years ago)
Author:
dglaser
Message:

#2388:

HeuristicLab.Services.Hive.DataAccess-3.3:

  • updated database schema
  • updated sql scripts
  • updated HiveStatisticsGenerator

HeuristicLab.Services.WebApp-3.3:

  • merged from trunk

HeuristicLab.Services.WebApp.Status-3.3:

  • updated data api controller

HeuristicLab.Services.WebApp.Statistics-3.3:

  • added exception page
  • improved jobs, clients, users and groups page
Location:
branches/HiveStatistics/sources
Files:
17 edited

Legend:

Unmodified
Added
Removed
  • branches/HiveStatistics/sources

  • branches/HiveStatistics/sources/HeuristicLab.Services.WebApp.Statistics/3.3/WebApp/clients/clients.cshtml

    r12525 r12551  
    33<header class="view-header">
    44    <ul class="nav nav-list nav-list-topbar pull-left">
    5     <li>
    6         <a ng-href="#/statistics/jobs">Jobs</a>
    7     </li>
    8     @if (Request.IsAuthenticated && User.IsInRole(HiveRoles.Administrator))
    9     {
    105        <li>
    11             <a ng-href="#/statistics/users">Users</a>
     6            <a ng-href="#/statistics/jobs">Jobs</a>
    127        </li>
    13     }
    14     <li class="active">
    15         <a ng-href="#/statistics/clients">Clients</a>
    16     </li>
    17     <li>
    18         <a ng-href="#/statistics/groups">Groups</a>
    19     </li>
     8        @if (Request.IsAuthenticated && User.IsInRole(HiveRoles.Administrator))
     9        {
     10            <li>
     11                <a ng-href="#/statistics/users">Users</a>
     12            </li>
     13        }
     14        <li class="active">
     15            <a ng-href="#/statistics/clients">Clients</a>
     16        </li>
     17        <li>
     18            <a ng-href="#/statistics/groups">Groups</a>
     19        </li>
     20        @if (Request.IsAuthenticated && User.IsInRole(HiveRoles.Administrator)) {
     21            <li>
     22                <a ng-href="#/statistics/exceptions">Exceptions</a>
     23            </li>
     24        }
    2025    </ul>
    2126</header>
     
    3742                            <th>Cores</th>
    3843                            <th>Cpu Utilization</th>
     44                            <th>Memory</th>
    3945                            <th>State</th>
    4046                            <th></th>
     
    5056                            <td>{{client.UsedCores}} / {{client.TotalCores}}</td>
    5157                            <td>{{client.CpuUtilization | number: 2}} %</td>
     58                            <td>{{client.UsedMemory | kbToGB}} / {{client.TotalMemory | kbToGB}} GB</td>
    5259                            <td>{{client.State}}</td>
    5360                            <td>
     
    5663                        </tr>
    5764                        <tr ng-hide="clientPage.Clients.length">
    58                             <td colspan="6" class="text-center">No clients found!</td>
     65                            <td colspan="7" class="text-center">No clients found!</td>
    5966                        </tr>
    6067                    </table>
     
    8289                                <th>Cores</th>
    8390                                <th>Cpu Utilization</th>
     91                                <th>Memory</th>
    8492                                <th>State</th>
    8593                                <th></th>
     
    9199                            <td>{{client.UsedCores}} / {{client.TotalCores}}</td>
    92100                            <td>{{client.CpuUtilization | number: 2}} %</td>
     101                            <td>{{client.UsedMemory | kbToGB}} / {{client.TotalMemory | kbToGB}} GB</td>
    93102                            <td>{{client.State}}</td>
    94103                            <td>
     
    97106                        </tr>
    98107                        <tr ng-hide="expiredClientPage.Clients.length">
    99                             <td colspan="6" class="text-center">No expired clients found!</td>
     108                            <td colspan="7" class="text-center">No expired clients found!</td>
    100109                        </tr>
    101110                    </table>
  • branches/HiveStatistics/sources/HeuristicLab.Services.WebApp.Statistics/3.3/WebApp/clients/details/clientDetails.cshtml

    r12525 r12551  
    1717            <a ng-href="#/statistics/groups">Groups</a>
    1818        </li>
     19        @if (Request.IsAuthenticated && User.IsInRole(HiveRoles.Administrator)) {
     20            <li>
     21                <a ng-href="#/statistics/exceptions">Exceptions</a>
     22            </li>
     23        }
    1924    </ul>
    2025</header>
     
    4651                                <tr>
    4752                                    <td class="text-left">Up Time:</td>
    48                                     <td>{{client.UpTime}}</td>
     53                                    <td>{{client.UpTime | toTimespan}}</td>
    4954                                </tr>
    5055                                <tr>
    5156                                    <td class="text-left">Last Update:</td>
    52                                     <td>{{client.LastUpdate}}</td>
     57                                    <td>{{client.LastUpdate | toDate}}</td>
    5358                                </tr>
    5459                            </table>
     
    5863                                <tr>
    5964                                    <td class="text-left">Total Unavailable Time:</td>
    60                                     <td class="text-right">{{client.TotalUnavailableTime}}</td>
     65                                    <td class="text-right">{{client.TotalUnavailableTime | toTimespan}}</td>
    6166                                </tr>
    6267                                <tr>
    6368                                    <td class="text-left">Total Calculating Time:</td>
    64                                     <td class="text-right">{{client.TotalCalculatingTime}}</td>
     69                                    <td class="text-right">{{client.TotalCalculatingTime | toTimespan}}</td>
    6570                                </tr>
    6671                                <tr>
    6772                                    <td class="text-left">Total Idle Time:</td>
    68                                     <td class="text-right">{{client.TotalIdleTime}}</td>
     73                                    <td class="text-right">{{client.TotalIdleTime | toTimespan}}</td>
    6974                                </tr>
    7075                                <tr>
    7176                                    <td class="text-left">Total Transferring Time:</td>
    72                                     <td class="text-right">{{client.TotalTransferringTime}}</td>
     77                                    <td class="text-right">{{client.TotalTransferringTime | toTimespan}}</td>
    7378                                </tr>
    7479                                <tr>
    7580                                    <td class="text-left">Total Offline Time:</td>
    76                                     <td class="text-right">{{client.TotalOfflineTime}}</td>
     81                                    <td class="text-right">{{client.TotalOfflineTime | toTimespan}}</td>
    7782                                </tr>
    7883                            </table>
     
    137142                        <knob knob-data="knobData.cpu" knob-options="knobOptions"></knob>
    138143                    </div>
     144                    <table class="table table-no-border table-condensed table-auto-width table-content">
     145                        <tr>
     146                            <td class="text-left">&nbsp;</td>
     147                            <td class="text-right">&nbsp;</td>
     148                        </tr>
     149                        <tr>
     150                            <td class="text-left">&nbsp;</td>
     151                            <td class="text-right">&nbsp;</td>
     152                        </tr>
     153                    </table>
    139154                </div>
    140155            </div>
     
    153168                        <tr>
    154169                            <td class="text-left">Total:</td>
    155                             <td class="text-right">{{client.TotalMemory | number}} GB</td>
     170                            <td class="text-right">{{client.TotalMemory | kbToGB}} GB</td>
    156171                        </tr>
    157172                        <tr>
    158173                            <td class="text-left">Used:</td>
    159                             <td class="text-right">{{client.UsedMemory | number}} GB</td>
     174                            <td class="text-right">{{client.UsedMemory | kbToGB}} GB</td>
    160175                        </tr>
    161176                    </table>
     
    163178            </div>
    164179        </div>
    165 
    166180    </div>
    167181</div>
     
    169183<div id="tasks-filter" class="default-filter-header text-center">
    170184    <form class="form-inline">
    171         <div class="form-group">
     185        <div class="form-group" style="margin-left: 5px; margin-right: 5px;">
    172186            <div class="btn-group" data-toggle="buttons">
    173187                <label class="btn btn-default" ng-class="{active: state.Selected}" ng-repeat="state in states"
     
    175189                    <input type="checkbox" autocomplete="off" checked> {{state.State}}
    176190                </label>
     191            </div>
     192        </div>
     193        <div class="form-group" style="margin-left: 5px; margin-right: 5px;">
     194            <div class="btn-group" dropdown dropdown-append-to-body>
     195                <button type="button" class="btn btn-default dropdown-toggle" dropdown-toggle>
     196                    {{curUserName}} <span class="caret"></span>
     197                </button>
     198                <ul class="dropdown-menu" role="menu">
     199                    <li>
     200                        <a ng-href="#/statistics/clients/{{client.Id}}"
     201                           ng-click="userChanged('00000000-0000-0000-0000-000000000000', 'All Users')">All Users</a>
     202                    </li>
     203                    <li class="divider"></li>
     204                    <li ng-repeat="user in client.Users">
     205                        <a ng-href="#/statistics/clients/{{client.Id}}"
     206                           ng-click="userChanged(user.Id, user.Name)">{{user.Name}}</a>
     207                    </li>
     208                </ul>
    177209            </div>
    178210        </div>
     
    210242                             </tr>
    211243                         }
    212                          <tr>
    213                              <td>Start Time:</td>
    214                              <td class="text-right">{{task.StartTime}}</td>
    215                          </tr>
    216                          <tr>
    217                              <td>End Time:</td>
    218                              <td class="text-right">{{task.EndTime}}</td>
    219                          </tr>
     244                        <tr>
     245                            <td>Start Time:</td>
     246                            <td ng-show="task.StartTime" class="text-right">{{task.StartTime | toDate}}</td>
     247                            <td ng-hide="task.StartTime" class="text-right">Not started</td>
     248                        </tr>
     249                        <tr>
     250                            <td>End Time:</td>
     251                            <td ng-show="task.EndTime" class="text-right">{{task.EndTime | toDate}}</td>
     252                            <td ng-hide="task.EndTime" class="text-right">Not finished</td>
     253                        </tr>
    220254                         <tr>
    221255                             <td>Calculating Time:</td>
    222                              <td class="text-right">{{task.CalculatingTime}}</td>
     256                             <td class="text-right">{{task.CalculatingTime | toTimespan}}</td>
    223257                         </tr>
    224258                         @if (Request.IsAuthenticated && User.IsInRole(HiveRoles.Administrator))
  • branches/HiveStatistics/sources/HeuristicLab.Services.WebApp.Statistics/3.3/WebApp/clients/details/clientDetailsCtrl.js

    r12516 r12551  
    44        ['$scope', '$stateParams', '$interval', 'app.statistics.clientService', 'app.statistics.taskService', '$modal',
    55        function ($scope, $stateParams, $interval, clientService, taskService, $modal) {
     6            $scope.curUserId = '00000000-0000-0000-0000-000000000000';
     7            $scope.curUserName = 'All Users';
    68            $scope.interval = defaultPageUpdateInterval;
    79            $scope.curTaskPage = 1;
     
    3335                clientService.getClientDetails({ id: $stateParams.id }, function (client) {
    3436                    $scope.client = client;
    35                     $scope.client.TotalMemory = Math.round($scope.client.TotalMemory / 1024);
    36                     $scope.client.UsedMemory = Math.round($scope.client.UsedMemory / 1024);
    3737                    $scope.knobData.cores = (client.UsedCores / client.TotalCores) * 100;
    3838                    $scope.knobData.cpu = client.CpuUtilization;
    3939                    $scope.knobData.memory = (client.UsedMemory / client.TotalMemory) * 100;
    40                     $scope.client.LastUpdate = CSharpDateToString($scope.client.LastUpdate);
    41                     $scope.client.UpTime = $scope.client.UpTime.toHHMMSS();
    42                     $scope.client.TotalUnavailableTime = $scope.client.TotalUnavailableTime.toHHMMSS();
    43                     $scope.client.TotalCalculatingTime = $scope.client.TotalCalculatingTime.toHHMMSS();
    44                     $scope.client.TotalIdleTime = $scope.client.TotalIdleTime.toHHMMSS();
    45                     $scope.client.TotalOfflineTime = $scope.client.TotalOfflineTime.toHHMMSS();
    46                     $scope.client.TotalTransferringTime = $scope.client.TotalTransferringTime.toHHMMSS();
    4740
    4841                    var length = client.TasksStates.length;
     
    8477                }
    8578
    86                 taskService.getTasksByClientId({ id: $stateParams.id, page: $scope.curTaskPage, size: $scope.taskPageSize }, states,
     79                taskService.getTasksByClientId({ id: $stateParams.id, page: $scope.curTaskPage, size: $scope.taskPageSize, userId: $scope.curUserId }, states,
    8780                    function (taskPage) {
    8881                        $scope.taskPage = taskPage;
    89                         var length = $scope.taskPage.Tasks.length;
    90                         for (var i = 0; i < length; ++i) {
    91                             $scope.taskPage.Tasks[i].TotalTime = $scope.taskPage.Tasks[i].TotalTime.toHHMMSS();
    92                             $scope.taskPage.Tasks[i].InitialWaitingTime = $scope.taskPage.Tasks[i].InitialWaitingTime.toHHMMSS();
    93                             $scope.taskPage.Tasks[i].WaitingTime = $scope.taskPage.Tasks[i].WaitingTime.toHHMMSS();
    94                             $scope.taskPage.Tasks[i].CalculatingTime = $scope.taskPage.Tasks[i].CalculatingTime.toHHMMSS();
    95                             $scope.taskPage.Tasks[i].TransferTime = $scope.taskPage.Tasks[i].TransferTime.toHHMMSS();
    96                             var startTime = $scope.taskPage.Tasks[i].StartTime;
    97                             if (isDefined(startTime)) {
    98                                 $scope.taskPage.Tasks[i].StartTime = CSharpDateToString(startTime);
    99                             } else {
    100                                 $scope.taskPage.Tasks[i].StartTime = 'Not started';
    101                             }
    102                             var endTime = $scope.taskPage.Tasks[i].EndTime;
    103                             if (isDefined(endTime)) {
    104                                 $scope.taskPage.Tasks[i].EndTime = CSharpDateToString(endTime);
    105                             } else {
    106                                 $scope.taskPage.Tasks[i].EndTime = 'Not finished';
    107                             }
    108                         }
    10982                    }
    11083                );
     
    12194                state.Selected = !state.Selected;
    12295                $scope.curTaskPage = 1;
     96                getClientDetails();
     97            };
     98
     99            $scope.userChanged = function(id, name) {
     100                $scope.curUserId = id;
     101                $scope.curUserName = name;
    123102                getClientDetails();
    124103            };
  • branches/HiveStatistics/sources/HeuristicLab.Services.WebApp.Statistics/3.3/WebApp/clients/details/clientTaskDetailsDialog.cshtml

    r12516 r12551  
    1414                            <tr>
    1515                                <td>Start Time:</td>
    16                                 <td class="text-right">{{task.StartTime}}</td>
     16                                <td ng-show="task.StartTime" class="text-left">{{task.StartTime | toDate}}</td>
     17                                <td ng-hide="task.StartTime" class="text-left">Not started</td>
    1718                            </tr>
    1819                            <tr>
    1920                                <td>End Time:</td>
    20                                 <td class="text-right">{{task.EndTime}}</td>
     21                                <td ng-show="task.EndTime" class="text-left">{{task.EndTime | toDate}}</td>
     22                                <td ng-hide="task.EndTime" class="text-left">Not finished</td>
    2123                            </tr>
    2224                            <tr>
     
    5860                            <tr>
    5961                                <td>Total Time:</td>
    60                                 <td>{{task.TotalTime}}</td>
     62                                <td>{{task.TotalTime | toTimespan}}</td>
    6163                            </tr>
    6264                            <tr>
    6365                                <td>Initial Waiting Time:</td>
    64                                 <td>{{task.InitialWaitingTime}}</td>
     66                                <td>{{task.InitialWaitingTime | toTimespan}}</td>
    6567                            </tr>
    6668                            <tr>
    6769                                <td>Waiting Time:</td>
    68                                 <td>{{task.WaitingTime}}</td>
     70                                <td>{{task.WaitingTime | toTimespan}}</td>
    6971                            </tr>
    7072                            <tr>
    7173                                <td>Calculating Time:</td>
    72                                 <td>{{task.CalculatingTime}}</td>
     74                                <td>{{task.CalculatingTime | toTimespan}}</td>
    7375                            </tr>
    7476                            <tr>
    7577                                <td>Transfer Time:</td>
    76                                 <td>{{task.TransferTime}}</td>
     78                                <td>{{task.TransferTime | toTimespan}}</td>
    7779                            </tr>
    7880                        </table>
     
    8284                            <tr>
    8385                                <td>Calculation Runs:</td>
    84                                 <td>{{task.NumCalculationRuns}}</td>
     86                                <td class="text-right">{{task.NumCalculationRuns}}</td>
    8587                            </tr>
    8688                            <tr>
    8789                                <td>Retries Runs:</td>
    88                                 <td>{{task.NumRetries}}</td>
     90                                <td class="text-right">{{task.NumRetries}}</td>
    8991                            </tr>
    9092                            <tr>
    9193                                <td>Cores Required:</td>
    92                                 <td>{{task.CoresRequired}}</td>
     94                                <td class="text-right">{{task.CoresRequired}}</td>
    9395                            </tr>
    9496                            <tr>
    9597                                <td>Memory Required:</td>
    96                                 <td>{{task.MemoryRequired}}</td>
     98                                <td class="text-right">{{task.MemoryRequired}} MB</td>
    9799                            </tr>
    98100                            <tr>
    99101                                <td>Priority:</td>
    100                                 <td>{{task.Priority}}</td>
     102                                <td class="text-right">{{task.Priority}}</td>
    101103                            </tr>
    102104                        </table>
  • branches/HiveStatistics/sources/HeuristicLab.Services.WebApp.Statistics/3.3/WebApp/groups/details/groupDetails.cshtml

    r12525 r12551  
    1616        <li class="active">
    1717            <a ng-href="#/statistics/groups">Groups</a>
    18         </li>
     18        </li>
     19        @if (Request.IsAuthenticated && User.IsInRole(HiveRoles.Administrator)) {
     20            <li>
     21                <a ng-href="#/statistics/exceptions">Exceptions</a>
     22            </li>
     23        }
    1924    </ul>
    2025</header>
     
    2227<div class="default-view-container">
    2328    <div class="row">
    24         <div class="col-lg-12">
     29        <div class="col-lg-9">
    2530            <div class="panel panel-default">
    2631                <div class="panel-heading">
     
    2934                <div class="panel-body">
    3035                    <div class="row">
    31                         <div class="col-md-5">
     36                        <div class="col-md-6">
    3237                            <table class="table table-no-border table-condensed table-auto-width table-content">
    3338                                <tr>
     
    3742                                <tr>
    3843                                    <td class="text-left">Clients:</td>
    39                                     <td class="text-right">{{group.Clients}}</td>
    40                                 </tr>
    41                                 <tr>
    42                                     <td class="text-left">Cpu Utilization:</td>
    43                                     <td class="text-right">{{group.CpuUtilization | number: 2}} %</td>
     44                                    <td class="text-right">{{group.OnlineClients}} / {{group.TotalClients}}</td>
    4445                                </tr>
    4546                            </table>
    4647                        </div>
    47                         <div class="col-md-5">
     48                        <div class="col-md-6">
    4849                            <table class="table table-no-border table-condensed table-auto-width table-content">
    4950                                <tr>
    50                                     <td class="text-left">TotalCores:</td>
    51                                     <td class="text-right">{{group.TotalCores}}</td>
    52                                 </tr>
    53                                 <tr>
    54                                     <td class="text-left">UsedCores:</td>
    55                                     <td class="text-right">{{group.UsedCores}}</td>
    56                                 </tr>
    57                                 <tr>
    58                                     <td class="text-left">Total Memory:</td>
    59                                     <td class="text-right">{{group.TotalMemory}}</td>
    60                                 </tr>
    61                                 <tr>
    62                                     <td class="text-left">Used Memory:</td>
    63                                     <td class="text-right">{{group.UsedMemory}}</td>
     51                                    <td class="text-left">Total Unavailable Time:</td>
     52                                    <td class="text-right">{{group.TotalUnavailableTime | toTimespan}}</td>
     53                                </tr>
     54                                <tr>
     55                                    <td class="text-left">Total Calculating Time:</td>
     56                                    <td class="text-right">{{group.TotalCalculatingTime | toTimespan}}</td>
     57                                </tr>
     58                                <tr>
     59                                    <td class="text-left">Total Idle Time:</td>
     60                                    <td class="text-right">{{group.TotalIdleTime | toTimespan}}</td>
     61                                </tr>
     62                                <tr>
     63                                    <td class="text-left">Total Transferring Time:</td>
     64                                    <td class="text-right">{{group.TotalTransferringTime | toTimespan}}</td>
     65                                </tr>
     66                                <tr>
     67                                    <td class="text-left">Total Offline Time:</td>
     68                                    <td class="text-right">{{group.TotalOfflineTime | toTimespan}}</td>
    6469                                </tr>
    6570                            </table>
    6671                        </div>
    67 
    68                         <div class="col-md-2"></div>
    69                     </div>
     72                    </div>
     73                </div>
     74            </div>
     75        </div>
     76        <div class="col-lg-3 col-md-6">
     77            <div class="panel panel-default">
     78                <div class="panel-heading">
     79                    <h3 class="panel-title">Tasks Overview</h3>
     80                </div>
     81                <div class="panel-body">
     82                    <table class="table table-no-border table-condensed table-auto-width table-content">
     83                        <tr>
     84                            <td class="text-left">Total:</td>
     85                            <td class="text-right">{{totalGroupTasks}}</td>
     86                        </tr>
     87                        <tr ng-repeat="state in group.TasksStates">
     88                            <td class="text-left">{{state.State}}:</td>
     89                            <td class="text-right">{{state.Count}}</td>
     90                        </tr>
     91                    </table>
    7092                </div>
    7193            </div>
    7294        </div>
    7395    </div>
     96
     97    <div class="row">
     98        <div class="col-lg-3 col-md-6">
     99            <div class="panel panel-default">
     100                <div class="panel-heading">
     101                    <h3 class="panel-title">Cores</h3>
     102                </div>
     103                <div class="panel-body">
     104                    <div class="text-center">
     105                        <knob knob-data="knobData.cores" knob-options="knobOptions"></knob>
     106                    </div>
     107                    <table class="table table-no-border table-condensed table-auto-width table-content">
     108                        <tr>
     109                            <td class="text-left">Total:</td>
     110                            <td class="text-right">{{group.TotalCores | number}}</td>
     111                        </tr>
     112                        <tr>
     113                            <td class="text-left">Used:</td>
     114                            <td class="text-right">{{group.UsedCores | number}}</td>
     115                        </tr>
     116                    </table>
     117                </div>
     118            </div>
     119        </div>
     120
     121        <div class="col-lg-3 col-md-6">
     122            <div class="panel panel-default">
     123                <div class="panel-heading">
     124                    <h3 class="panel-title">CPU Utilization</h3>
     125                </div>
     126                <div class="panel-body">
     127                    <div class="text-center">
     128                        <knob knob-data="knobData.cpu" knob-options="knobOptions"></knob>
     129                    </div>
     130                    <table class="table table-no-border table-condensed table-auto-width table-content">
     131                        <tr>
     132                            <td class="text-left">Total:</td>
     133                            <td class="text-right">{{group.TotalCpuUtilization | number: 2}} %</td>
     134                        </tr>
     135                        <tr>
     136                            <td class="text-left">Active:</td>
     137                            <td class="text-right">{{group.ActiveCpuUtilization | number: 2}} %</td>
     138                        </tr>
     139                    </table>
     140                </div>
     141            </div>
     142        </div>
     143
     144        <div class="col-lg-3 col-md-6">
     145            <div class="panel panel-default">
     146                <div class="panel-heading">
     147                    <h3 class="panel-title">Memory</h3>
     148                </div>
     149                <div class="panel-body">
     150                    <div class="text-center">
     151                        <knob knob-data="knobData.memory" knob-options="knobOptions"></knob>
     152                    </div>
     153                    <table class="table table-no-border table-condensed table-auto-width table-content">
     154                        <tr>
     155                            <td class="text-left">Total:</td>
     156                            <td class="text-right">{{group.TotalMemory | kbToGB}} GB</td>
     157                        </tr>
     158                        <tr>
     159                            <td class="text-left">Used:</td>
     160                            <td class="text-right">{{group.UsedMemory | kbToGB}} GB</td>
     161                        </tr>
     162                    </table>
     163                </div>
     164            </div>
     165        </div>
     166    </div>
     167
    74168    <div class="row">
    75169        <div class="col-lg-12">
     
    86180                                <th>Cores</th>
    87181                                <th>Cpu Utilization</th>
     182                                <th>Memory</th>
    88183                                <th>State</th>
    89184                                <th></th>
     
    95190                            <td>{{client.UsedCores}} / {{client.TotalCores}}</td>
    96191                            <td>{{client.CpuUtilization | number: 2}} %</td>
     192                            <td>{{client.UsedMemory | kbToGB}} / {{client.TotalMemory | kbToGB}}</td>
    97193                            <td>{{client.State}}</td>
    98194                            <td>
     
    101197                        </tr>
    102198                        <tr ng-hide="clientPage.Clients.length">
    103                             <td colspan="6" class="text-center">No clients found!</td>
     199                            <td colspan="7" class="text-center">No clients found!</td>
    104200                        </tr>
    105201                    </table>
  • branches/HiveStatistics/sources/HeuristicLab.Services.WebApp.Statistics/3.3/WebApp/groups/details/groupDetailsCtrl.js

    r12525 r12551  
    88            $scope.clientsPageSize = 20;
    99
     10
     11            // details
     12            $scope.knobOptions = {
     13                'fgColor': "#f7921d",
     14                'angleOffset': -125,
     15                'angleArc': 250,
     16                'readOnly': true,
     17                'width': "80%",
     18                'targetvalue': "100",
     19                'format': function (value) {
     20                    return value;
     21                },
     22                draw: function () {
     23                    $(this.i).val(this.cv + '%');
     24                }
     25            };
     26
     27            $scope.knobData = {
     28                cores: 0,
     29                cpu: 0,
     30                memory: 0
     31            };
     32
    1033            var getGroupDetails = function() {
    1134                groupService.getGroupDetails({ id: $stateParams.id }, function (group) {
    1235                    $scope.group = group;
     36                    $scope.knobData.cores = (group.UsedCores / group.TotalCores) * 100;
     37                    $scope.knobData.cpu = group.ActiveCpuUtilization;
     38                    $scope.knobData.memory = (group.UsedMemory / group.TotalMemory) * 100;
     39
     40                    var length = group.TasksStates.length;
     41                    var total = 0;
     42                    for (var i = 0; i < length; ++i) {
     43                        total += group.TasksStates[i].Count;
     44                    }
     45                    $scope.totalGroupTasks = total;
    1346                });
    1447            };
  • branches/HiveStatistics/sources/HeuristicLab.Services.WebApp.Statistics/3.3/WebApp/groups/groups.cshtml

    r12525 r12551  
    1616        <li class="active">
    1717            <a ng-href="#/statistics/groups">Groups</a>
    18         </li>
     18        </li>
     19        @if (Request.IsAuthenticated && User.IsInRole(HiveRoles.Administrator)) {
     20            <li>
     21                <a ng-href="#/statistics/exceptions">Exceptions</a>
     22            </li>
     23        }
    1924    </ul>
    2025</header>
     
    3540                            <th>Cores</th>
    3641                            <th>Cpu Utilization</th>
     42                            <th>Memory</th>
    3743                            <th>Clients</th>
    3844                            <th></th>
     
    4450                            <td>{{group.UsedCores}} / {{group.TotalCores}}</td>
    4551                            <td>{{group.CpuUtilization | number: 2}} %</td>
    46                             <td>{{group.Clients}}</td>
     52                            <td>{{group.UsedMemory | kbToGB}} / {{group.TotalMemory | kbToGB}} GB</td>
     53                            <td>{{group.OnlineClients}} / {{group.TotalClients}}</td>
    4754                            <td>
    4855                                <a ng-href="#/statistics/groups/{{group.Id}}">Details</a>
     
    5057                        </tr>
    5158                        <tr ng-hide="groupPage.Groups.length">
    52                             <td colspan="6" class="text-center">No groups found!</td>
     59                            <td colspan="7" class="text-center">No groups found!</td>
    5360                        </tr>
    5461                    </table>
  • branches/HiveStatistics/sources/HeuristicLab.Services.WebApp.Statistics/3.3/WebApp/jobs/details/jobDetails.cshtml

    r12525 r12551  
    1717            <a ng-href="#/statistics/groups">Groups</a>
    1818        </li>
     19        @if (Request.IsAuthenticated && User.IsInRole(HiveRoles.Administrator)) {
     20            <li>
     21                <a ng-href="#/statistics/exceptions">Exceptions</a>
     22            </li>
     23        }
    1924    </ul>
    2025</header>
     
    3742                                <tr>
    3843                                    <td class="text-left">Created at:</td>
    39                                     <td>{{job.DateCreated}}</td>
     44                                    <td>{{job.DateCreated | toDate}}</td>
    4045                                </tr>
    4146                                <tr>
    4247                                    <td class="text-left">Completed at:</td>
    43                                     <td>{{job.DateCompleted}}</td>
     48                                    <td ng-show="job.DateCompleted">{{job.DateCompleted | toDate}}</td>
     49                                    <td ng-hide="job.DateCompleted">Not completed yet</td>
    4450                                </tr>
    4551                                @if (Request.IsAuthenticated && User.IsInRole(HiveRoles.Administrator)) {
     
    6167                                <tr>
    6268                                    <td class="text-left">Total Time:</td>
    63                                     <td class="text-right">{{job.TotalTime}}</td>
     69                                    <td class="text-right">{{job.TotalTime | toTimespan}}</td>
    6470                                </tr>
    6571                                <tr>
    6672                                    <td class="text-left">Total Calculating Time:</td>
    67                                     <td class="text-right">{{job.TotalCalculatingTime}}</td>
     73                                    <td class="text-right">{{job.TotalCalculatingTime | toTimespan}}</td>
    6874                                </tr>
    6975                                <tr>
    7076                                    <td class="text-left">Total Waiting Time:</td>
    71                                     <td class="text-right">{{job.TotalWaitingTime}}</td>
     77                                    <td class="text-right">{{job.TotalWaitingTime | toTimespan}}</td>
    7278                                </tr>
    7379                                <tr>
     
    8187                                <tr>
    8288                                    <td class="text-left">Min Calculating Time:</td>
    83                                     <td class="text-right">{{job.MinCalculatingTime}}</td>
     89                                    <td class="text-right">{{job.MinCalculatingTime | toTimespan}}</td>
    8490                                </tr>
    8591                                <tr>
    8692                                    <td class="text-left">Max Calculating Time:</td>
    87                                     <td class="text-right">{{job.MaxCalculatingTime}}</td>
     93                                    <td class="text-right">{{job.MaxCalculatingTime | toTimespan}}</td>
    8894                                </tr>
    8995                                <tr>
    9096                                    <td class="text-left">Avg. Calculating Time:</td>
    91                                     <td class="text-right">{{job.AvgCalculatingTime}}</td>
     97                                    <td class="text-right">{{job.AvgCalculatingTime | toTimespan}}</td>
    9298                                </tr>
    9399                                <tr>
    94100                                    <td class="text-left">Avg. Transferring Time:</td>
    95                                     <td class="text-right">{{job.AvgTransferringTime}}</td>
     101                                    <td class="text-right">{{job.AvgTransferringTime | toTimespan}}</td>
    96102                                </tr>
    97103                            </table>
     
    158164                        <tr>
    159165                            <td>Start Time:</td>
    160                             <td class="text-right">{{task.StartTime}}</td>
     166                            <td ng-show="task.StartTime" class="text-right">{{task.StartTime | toDate}}</td>
     167                            <td ng-hide="task.StartTime" class="text-right">Not started</td>
    161168                        </tr>
    162169                        <tr>
    163170                            <td>End Time:</td>
    164                             <td class="text-right">{{task.EndTime}}</td>
     171                            <td ng-show="task.EndTime" class="text-right">{{task.EndTime | toDate}}</td>
     172                            <td ng-hide="task.EndTime" class="text-right">Not finished</td>
    165173                        </tr>
    166174                        <tr>
    167175                            <td>Calculating Time:</td>
    168                             <td class="text-right">{{task.CalculatingTime}}</td>
     176                            <td class="text-right">{{task.CalculatingTime | toTimespan}}</td>
    169177                        </tr>
    170178                        <tr>
  • branches/HiveStatistics/sources/HeuristicLab.Services.WebApp.Statistics/3.3/WebApp/jobs/details/jobDetailsCtrl.js

    r12525 r12551  
    1111                jobService.getJobDetails({ id: $stateParams.id }, function (job) {
    1212                    $scope.job = job;
    13                     $scope.job.DateCreated = CSharpDateToString($scope.job.DateCreated);
    14                     if (isDefined($scope.job.DateCompleted)) {
    15                         $scope.job.DateCompleted = CSharpDateToString($scope.job.DateCompleted);
    16                     } else {
    17                         $scope.job.DateCompleted = 'Not completed yet';
    18                     }
    1913                    $scope.job.CalculatingWaitingRatio = ($scope.job.TotalCalculatingTime / $scope.job.TotalWaitingTime);
    20                     $scope.job.AvgTransferringTime = $scope.job.AvgTransferringTime.toHHMMSS();
    21                     $scope.job.AvgCalculatingTime = $scope.job.AvgCalculatingTime.toHHMMSS();
    22                     $scope.job.MinCalculatingTime = $scope.job.MinCalculatingTime.toHHMMSS();
    23                     $scope.job.MaxCalculatingTime = $scope.job.MaxCalculatingTime.toHHMMSS();
    24                     $scope.job.TotalCalculatingTime = $scope.job.TotalCalculatingTime.toHHMMSS();
    25                     $scope.job.TotalWaitingTime = $scope.job.TotalWaitingTime.toHHMMSS();
    26                     $scope.job.TotalTime = $scope.job.TotalTime.toHHMMSS();
    2714
    2815                    var length = job.TasksStates.length;
     
    6653                    function (taskPage) {
    6754                        $scope.taskPage = taskPage;
    68                         var length = $scope.taskPage.Tasks.length;
    69                         for (var i = 0; i < length; ++i) {
    70                             $scope.taskPage.Tasks[i].TotalTime = $scope.taskPage.Tasks[i].TotalTime.toHHMMSS();
    71                             $scope.taskPage.Tasks[i].InitialWaitingTime = $scope.taskPage.Tasks[i].InitialWaitingTime.toHHMMSS();
    72                             $scope.taskPage.Tasks[i].WaitingTime = $scope.taskPage.Tasks[i].WaitingTime.toHHMMSS();
    73                             $scope.taskPage.Tasks[i].CalculatingTime = $scope.taskPage.Tasks[i].CalculatingTime.toHHMMSS();
    74                             $scope.taskPage.Tasks[i].TransferTime = $scope.taskPage.Tasks[i].TransferTime.toHHMMSS();
    75                             var startTime = $scope.taskPage.Tasks[i].StartTime;
    76                             if (isDefined(startTime)) {
    77                                 $scope.taskPage.Tasks[i].StartTime = CSharpDateToString(startTime);
    78                             } else {
    79                                 $scope.taskPage.Tasks[i].StartTime = 'Not started';
    80                             }
    81                             var endTime = $scope.taskPage.Tasks[i].EndTime;
    82                             if (isDefined(endTime)) {
    83                                 $scope.taskPage.Tasks[i].EndTime = CSharpDateToString(endTime);
    84                             } else {
    85                                 $scope.taskPage.Tasks[i].EndTime = 'Not finished';
    86                             }
    87                         }
    8855                    }
    8956                );
  • branches/HiveStatistics/sources/HeuristicLab.Services.WebApp.Statistics/3.3/WebApp/jobs/details/jobTaskDetailsDialog.cshtml

    r12516 r12551  
    1212                            <tr>
    1313                                <td>Start Time:</td>
    14                                 <td class="text-right">{{task.StartTime}}</td>
     14                                <td ng-show="task.StartTime" class="text-left">{{task.StartTime | toDate}}</td>
     15                                <td ng-hide="task.StartTime" class="text-left">Not started</td>
    1516                            </tr>
    1617                            <tr>
    1718                                <td>End Time:</td>
    18                                 <td class="text-right">{{task.EndTime}}</td>
     19                                <td ng-show="task.EndTime" class="text-left">{{task.EndTime | toDate}}</td>
     20                                <td ng-hide="task.EndTime" class="text-left">Not finished</td>
    1921                            </tr>
    2022                            <tr>
     
    3739                            <tr>
    3840                                <td>Total Time:</td>
    39                                 <td>{{task.TotalTime}}</td>
     41                                <td>{{task.TotalTime | toTimespan}}</td>
    4042                            </tr>
    4143                            <tr>
    4244                                <td>Initial Waiting Time:</td>
    43                                 <td>{{task.InitialWaitingTime}}</td>
     45                                <td>{{task.InitialWaitingTime | toTimespan}}</td>
    4446                            </tr>
    4547                            <tr>
    4648                                <td>Waiting Time:</td>
    47                                 <td>{{task.WaitingTime}}</td>
     49                                <td>{{task.WaitingTime | toTimespan}}</td>
    4850                            </tr>
    4951                            <tr>
    5052                                <td>Calculating Time:</td>
    51                                 <td>{{task.CalculatingTime}}</td>
     53                                <td>{{task.CalculatingTime | toTimespan}}</td>
    5254                            </tr>
    5355                            <tr>
    5456                                <td>Transfer Time:</td>
    55                                 <td>{{task.TransferTime}}</td>
     57                                <td>{{task.TransferTime | toTimespan}}</td>
    5658                            </tr>
    5759                        </table>
     
    6163                            <tr>
    6264                                <td>Calculation Runs:</td>
    63                                 <td>{{task.NumCalculationRuns}}</td>
     65                                <td class="text-right">{{task.NumCalculationRuns}}</td>
    6466                            </tr>
    6567                            <tr>
    6668                                <td>Retries Runs:</td>
    67                                 <td>{{task.NumRetries}}</td>
     69                                <td class="text-right">{{task.NumRetries}}</td>
    6870                            </tr>
    6971                            <tr>
    7072                                <td>Cores Required:</td>
    71                                 <td>{{task.CoresRequired}}</td>
     73                                <td class="text-right">{{task.CoresRequired}}</td>
    7274                            </tr>
    7375                            <tr>
    7476                                <td>Memory Required:</td>
    75                                 <td>{{task.MemoryRequired}}</td>
     77                                <td class="text-right">{{task.MemoryRequired}} MB</td>
    7678                            </tr>
    7779                            <tr>
    7880                                <td>Priority:</td>
    79                                 <td>{{task.Priority}}</td>
     81                                <td class="text-right">{{task.Priority}}</td>
    8082                            </tr>
    8183                        </table>
  • branches/HiveStatistics/sources/HeuristicLab.Services.WebApp.Statistics/3.3/WebApp/jobs/jobs.cshtml

    r12525 r12551  
    1717            <a ng-href="#/statistics/groups">Groups</a>
    1818        </li>
     19        @if (Request.IsAuthenticated && User.IsInRole(HiveRoles.Administrator)) {
     20            <li>
     21                <a ng-href="#/statistics/exceptions">Exceptions</a>
     22            </li>
     23        }
    1924    </ul>
    2025</header>
     
    3338                            <th>#</th>
    3439                            <th>Job Name</th>
     40                            @if (Request.IsAuthenticated && User.IsInRole(HiveRoles.Administrator)) {
     41                                <th>User Name</th>
     42                            }
    3543                            <th>Date Created</th>
    3644                            <th>Progress</th>
     
    3846                        </tr>
    3947                        </thead>
    40                         <tr ng-repeat="job in jobs">
    41                             <td>{{$index + 1}}</td>
    42                             <td>{{job.Name}}</td>
    43                             <td>{{job.DateCreated}}</td>
    44                             <td>
    45                                 <progressbar class="progress active" max="job.TotalTasks" value="job.CompletedTasks" type="success"><i style="color:black; white-space:nowrap;">{{job.CompletedTasks}} / {{job.TotalTasks}}</i></progressbar>
    46                             </td>
    47                             <td>
    48                                 <a ng-href="#/statistics/jobs/{{job.Id}}">Details</a>
    49                             </td>
    50                         </tr>
    51                         <tr ng-hide="jobs.length">
    52                             <td colspan="5" class="text-center">No active jobs found!</td>
    53                         </tr>
    54                     </table>
    55                 </div>
    56             </div>
    57         </div>
    58     </div>
    59     @if (Request.IsAuthenticated && User.IsInRole(HiveRoles.Administrator)) {
    60         <div class="row">
    61             <div class="col-lg-12">
    62                 <div class="panel panel-default">
    63                     <div class="panel-heading">
    64                         <h3 class="panel-title">Current Active Jobs</h3>
    65                     </div>
    66                     <div class="panel-body">
    67                         <table class="table table-hover table-condensed">
    68                             <thead>
    69                                 <tr>
    70                                     <th>#</th>
    71                                     <th>Job Name</th>
    72                                     <th>User Name</th>
    73                                     <th>Date Created</th>
    74                                     <th>Progress</th>
    75                                     <th></th>
    76                                 </tr>
    77                             </thead>
     48                        @if (Request.IsAuthenticated && User.IsInRole(HiveRoles.Administrator)) {
    7849                            <tr ng-repeat="job in allUsersJobs">
    7950                                <td>{{$index + 1}}</td>
     
    8253                                    <a ng-href="#/statistics/users/{{job.UserId}}" ng-show="job.UserName">{{job.UserName}}</a>
    8354                                </td>
    84                                 <td>{{job.DateCreated}}</td>
     55                                <td>{{job.DateCreated | toDate}}</td>
    8556                                <td>
    8657                                    <progressbar class="progress active" max="job.TotalTasks" value="job.CompletedTasks" type="success"><i style="color:black; white-space:nowrap;">{{job.CompletedTasks}} / {{job.TotalTasks}}</i></progressbar>
     
    9364                                <td colspan="6" class="text-center">No active jobs found!</td>
    9465                            </tr>
    95                         </table>
    96                     </div>
     66                        } else {
     67                            <tr ng-repeat="job in jobs">
     68                                <td>{{$index + 1}}</td>
     69                                <td>{{job.Name}}</td>
     70                                <td>{{job.DateCreated | toDate}}</td>
     71                                <td>
     72                                    <progressbar class="progress active" max="job.TotalTasks" value="job.CompletedTasks" type="success"><i style="color: black; white-space: nowrap;">{{job.CompletedTasks}} / {{job.TotalTasks}}</i></progressbar>
     73                                </td>
     74                                <td>
     75                                    <a ng-href="#/statistics/jobs/{{job.Id}}">Details</a>
     76                                </td>
     77                            </tr>
     78                            <tr ng-hide="jobs.length">
     79                                <td colspan="5" class="text-center">No active jobs found!</td>
     80                            </tr>
     81                        }
     82                    </table>
    9783                </div>
    9884            </div>
    9985        </div>
    100     }
     86    </div>
     87
    10188    <div class="row">
    10289        <div class="col-lg-12">
     
    120107                            <td>{{($index + 1)+((completedJobCurPage-1)*(completedJobPageSize))}}</td>
    121108                            <td>{{job.Name}}</td>
    122                             <td>{{job.DateCreated}}</td>
    123                             <td>{{job.DateCompleted}}</td>
     109                            <td>{{job.DateCreated | toDate}}</td>
     110                            <td>{{job.DateCompleted | toDate}}</td>
    124111                            <td>{{job.TotalTasks}}</td>
    125112                            <td><a ng-href="#/statistics/jobs/{{job.Id}}">Details</a></td>
  • branches/HiveStatistics/sources/HeuristicLab.Services.WebApp.Statistics/3.3/WebApp/jobs/jobsCtrl.js

    r12525 r12551  
    1212                jobService.getAllJobs({ completed: false }, function(jobs) {
    1313                    $scope.jobs = jobs;
    14                     var length = $scope.jobs.length;
    15                     for (var i = 0; i < length; ++i) {
    16                         $scope.jobs[i].DateCreated = CSharpDateToString($scope.jobs[i].DateCreated);
    17                     }
    1814                });
    1915            };
     
    2319                    function (jobPage) {
    2420                        $scope.completedJobPage = jobPage;
    25                         var length = $scope.completedJobPage.Jobs.length;
    26                         for (var i = 0; i < length; ++i) {
    27                             $scope.completedJobPage.Jobs[i].DateCreated = CSharpDateToString($scope.completedJobPage.Jobs[i].DateCreated);
    28                             $scope.completedJobPage.Jobs[i].DateCompleted = CSharpDateToString($scope.completedJobPage.Jobs[i].DateCompleted);
    29                         }
    3021                    }
    3122                );
     
    3627                    $scope.isAdministrator = true;
    3728                    $scope.allUsersJobs = jobs;
    38                     var length = $scope.allUsersJobs.length;
    39                     for (var i = 0; i < length; ++i) {
    40                         $scope.allUsersJobs[i].DateCreated = CSharpDateToString($scope.allUsersJobs[i].DateCreated);
    41                     }
    4229                });
    4330            };
  • branches/HiveStatistics/sources/HeuristicLab.Services.WebApp.Statistics/3.3/WebApp/services/clientService.js

    r12525 r12551  
    44    module.factory('app.statistics.clientService',
    55        ['$resource', function ($resource) {
    6             return $resource(apiUrl + ':action', { id: '@id', page: '@page', size: '@size', states: '@states', expired: '@expired', start: '@start', end: '@end' }, {
     6            return $resource(apiUrl + ':action', { id: '@id', page: '@page', size: '@size', states: '@states', expired: '@expired', start: '@start', end: '@end', userId: '@userId' }, {
    77                getClientDetails: { method: 'GET', params: { action: 'GetClientDetails' } },
    88                getClients: { method: 'GET', params: { action: 'GetClients' } },
  • branches/HiveStatistics/sources/HeuristicLab.Services.WebApp.Statistics/3.3/WebApp/users/details/userDetails.cshtml

    r12525 r12551  
    1616            <a ng-href="#/statistics/groups">Groups</a>
    1717        </li>
     18        @if (Request.IsAuthenticated && User.IsInRole(HiveRoles.Administrator)) {
     19            <li>
     20                <a ng-href="#/statistics/exceptions">Exceptions</a>
     21            </li>
     22        }
    1823    </ul>
    1924</header>
     
    4651                        <tr>
    4752                            <td class="text-left">Total:</td>
    48                             <td class="text-right">{{totalJobTasks}}</td>
     53                            <td class="text-right">{{totalUserTasks}}</td>
    4954                        </tr>
    50                         <tr ng-repeat="state in states">
     55                        <tr ng-repeat="state in user.TasksStates">
    5156                            <td class="text-left">{{state.State}}:</td>
    5257                            <td class="text-right">{{state.Count}}</td>
     
    7883                            <td>{{$index + 1}}</td>
    7984                            <td>{{job.Name}}</td>
    80                             <td>{{job.DateCreated}}</td>
     85                            <td>{{job.DateCreated | toDate}}</td>
    8186                            <td>
    8287                                <progressbar class="progress active" max="job.TotalTasks" value="job.CompletedTasks" type="success"><i style="color:black; white-space:nowrap;">{{job.CompletedTasks}} / {{job.TotalTasks}}</i></progressbar>
     
    116121                            <td>{{($index + 1)+((completedJobCurPage-1)*(completedJobPageSize))}}</td>
    117122                            <td>{{job.Name}}</td>
    118                             <td>{{job.DateCreated}}</td>
    119                             <td>{{job.DateCompleted}}</td>
     123                            <td>{{job.DateCreated | toDate}}</td>
     124                            <td>{{job.DateCompleted | toDate}}</td>
    120125                            <td>{{job.TotalTasks}}</td>
    121126                            <td><a ng-href="#/statistics/jobs/{{job.Id}}">Details</a></td>
     
    135140        </div>
    136141    </div>
    137 
    138142</div>
    139143}
  • branches/HiveStatistics/sources/HeuristicLab.Services.WebApp.Statistics/3.3/WebApp/users/details/userDetailsCtrl.js

    r12516 r12551  
    1212                userService.getUser({ id: $stateParams.id }, function(user) {
    1313                    $scope.user = user;
     14
     15                    var length = user.TasksStates.length;
     16                    var total = 0;
     17                    for (var i = 0; i < length; ++i) {
     18                        total += user.TasksStates[i].Count;
     19                    }
     20                    $scope.totalUserTasks = total;
    1421                });
    1522            };
     
    1825                jobService.getAllJobsByUserId({ id: $stateParams.id, completed: false }, function (jobs) {
    1926                    $scope.jobs = jobs;
    20                     var length = $scope.jobs.length;
    21                     for (var i = 0; i < length; ++i) {
    22                         $scope.jobs[i].DateCreated = CSharpDateToString($scope.jobs[i].DateCreated);
    23                     }
    2427                });
    2528            };
     
    2932                    function (jobPage) {
    3033                        $scope.completedJobPage = jobPage;
    31                         var length = $scope.completedJobPage.Jobs.length;
    32                         for (var i = 0; i < length; ++i) {
    33                             $scope.completedJobPage.Jobs[i].DateCreated = CSharpDateToString($scope.completedJobPage.Jobs[i].DateCreated);
    34                             $scope.completedJobPage.Jobs[i].DateCompleted = CSharpDateToString($scope.completedJobPage.Jobs[i].DateCompleted);
    35                         }
    3634                    }
    3735                );
  • branches/HiveStatistics/sources/HeuristicLab.Services.WebApp.Statistics/3.3/WebApp/users/users.cshtml

    r12525 r12551  
    1616            <a ng-href="#/statistics/groups">Groups</a>
    1717        </li>
     18        @if (Request.IsAuthenticated && User.IsInRole(HiveRoles.Administrator)) {
     19            <li>
     20                <a ng-href="#/statistics/exceptions">Exceptions</a>
     21            </li>
     22        }
    1823    </ul>
    1924</header>
Note: See TracChangeset for help on using the changeset viewer.