Index: /branches/WebJobManager/HeuristicLab.Clients.Hive.WebJobManager/Controllers/UserController.cs
===================================================================
--- /branches/WebJobManager/HeuristicLab.Clients.Hive.WebJobManager/Controllers/UserController.cs	(revision 13847)
+++ /branches/WebJobManager/HeuristicLab.Clients.Hive.WebJobManager/Controllers/UserController.cs	(revision 13848)
@@ -36,4 +36,5 @@
         /// </summary>
         /// <returns></returns>
+        
         private bool init()
         {
@@ -76,5 +77,5 @@
             }
         }
-
+        
         public IActionResult SelectUser(string id)
         {
Index: /branches/WebJobManager/HeuristicLab.Clients.Hive.WebJobManager/Scripts/Hubs/GraphHubber.js
===================================================================
--- /branches/WebJobManager/HeuristicLab.Clients.Hive.WebJobManager/Scripts/Hubs/GraphHubber.js	(revision 13847)
+++ /branches/WebJobManager/HeuristicLab.Clients.Hive.WebJobManager/Scripts/Hubs/GraphHubber.js	(revision 13848)
@@ -1,4 +1,3 @@
 ﻿var hubber = $.connection.jobUpdaterHub;
-
 $(function () {
   //  $.connection.hub.logging = true;
@@ -28,5 +27,5 @@
                 console.log("#REFRESH ALL");
 
-            }, 5000);
+            }, 5000 + (dataCollection.length * 500));
         }
     }
Index: /branches/WebJobManager/HeuristicLab.Clients.Hive.WebJobManager/Startup.cs
===================================================================
--- /branches/WebJobManager/HeuristicLab.Clients.Hive.WebJobManager/Startup.cs	(revision 13847)
+++ /branches/WebJobManager/HeuristicLab.Clients.Hive.WebJobManager/Startup.cs	(revision 13848)
@@ -40,4 +40,5 @@
             });
             services.AddSingleton<IHiveServiceLocator, HiveServiceLocatorWeb>();
+            services.AddCaching();
             services.AddSignalR();
         }
Index: /branches/WebJobManager/HeuristicLab.Clients.Hive.WebJobManager/Views/Shared/Navbar.cshtml
===================================================================
--- /branches/WebJobManager/HeuristicLab.Clients.Hive.WebJobManager/Views/Shared/Navbar.cshtml	(revision 13847)
+++ /branches/WebJobManager/HeuristicLab.Clients.Hive.WebJobManager/Views/Shared/Navbar.cshtml	(revision 13848)
@@ -6,4 +6,5 @@
         class="@(Model.Active == "Job" ? "active" : "")">
         <a asp-controller="Job"
+           accesskey="j"
            asp-action="Index">
             Job management
@@ -17,5 +18,6 @@
             {
                 <a asp-controller="User"
-                   asp-action="Index">
+                   asp-action="Index"
+                   accesskey="u">
                     User management
                 </a>
@@ -34,5 +36,6 @@
             {
             <a asp-controller="Resource"
-               asp-action="Index">
+               asp-action="Index"
+               accesskey="r">
                 Resources
             </a>
@@ -50,4 +53,5 @@
         <a asp-controller="Home"
            asp-action="Logout"
+           accesskey="l"
            class="text-danger">
             Logout
Index: /branches/WebJobManager/HeuristicLab.Clients.Hive.WebJobManager/Views/User/Index.cshtml
===================================================================
--- /branches/WebJobManager/HeuristicLab.Clients.Hive.WebJobManager/Views/User/Index.cshtml	(revision 13847)
+++ /branches/WebJobManager/HeuristicLab.Clients.Hive.WebJobManager/Views/User/Index.cshtml	(revision 13848)
@@ -309,6 +309,34 @@
                                 <div class="form-group">
                                     <label class="col-sm-3 control-label">
-                                        @Model.SelectedUserRoles.Count Roles
+                                        @Model.SelectedUserRoles.Count Roles <br />
+                                        @if (Model.SelectedUserRoles.Where(x => x.Name == "Hive User").Count() != 0)
+                                        {
+                                            if (Model.SelectedUserRoles.Where(x => x.Name == "AccessService Administrator").Count() != 0)
+                                            {
+                                                if (Model.SelectedUserRoles.Where(x => x.Name == "Hive Administrator").Count() != 0)
+                                                {
+                                                    <span style="color:forestgreen">Job management<br/>User management<br />Resources</span>
+
+                                                }
+                                                else
+                                                {
+                                                    <span style="color:forestgreen">Job management<br />User management</span>
+
+                                                }
+                                            }
+                                            else
+                                            {
+                                                <span style="color:forestgreen">Job management</span>
+
+                                            }
+
+                                        }
+                                        else
+                                        {
+                                            <span style="color:darkred">No access to Hive</span>
+
+                                        }
                                     </label>
+                                    
                                     <div class="col-sm-8 control-label" style="text-align:left">
                                         @if (Model.SelectedUserRoles.Count > 0)
@@ -368,4 +396,9 @@
                                                                onclick="triggerSave()">
                                                         @role.Name
+                                                        <span style="color:forestgreen">
+                                                            @(role.Name == "Hive User" ? " (access to Hive and job manager)" : "")
+                                                            @(role.Name == "Hive Administrator" ? " (access to resources)" : "")
+                                                            @(role.Name == "AccessService Administrator" ? " (access to user manager)" : "")
+                                                        </span>
                                                     </label>
                                                 </div>
Index: /branches/WebJobManager/HeuristicLab.Clients.Hive.WebJobManager/Views/User/Roles.cshtml
===================================================================
--- /branches/WebJobManager/HeuristicLab.Clients.Hive.WebJobManager/Views/User/Roles.cshtml	(revision 13847)
+++ /branches/WebJobManager/HeuristicLab.Clients.Hive.WebJobManager/Views/User/Roles.cshtml	(revision 13848)
@@ -66,4 +66,9 @@
                        onclick="showRole()">
                         @role.Name
+                        <span style="color:forestgreen">
+                            @(role.Name == "Hive User" ? " (Hive + job manager)" : "")
+                            @(role.Name == "Hive Administrator" ? " (Resources)" : "")
+                            @(role.Name == "AccessService Administrator" ? " (User manager)" : "")
+                        </span>
                     </a>
                 }
@@ -101,5 +106,11 @@
                         @if (Model.SelectedRole.Name != "")
                         {
-                            <i class="fa fa-gavel "></i> @Model.SelectedRole.Name;
+                            <i class="fa fa-gavel "></i> @Model.SelectedRole.Name
+                            <span style="color:forestgreen">
+                                @(Model.SelectedRole.Name == "Hive User" ? " (access to Hive and job manager)" : "")
+                                @(Model.SelectedRole.Name == "Hive Administrator" ? " (access to resources)" : "")
+                                @(Model.SelectedRole.Name == "AccessService Administrator" ? " (access to user manager)" : "")
+                            </span>
+
                         }
                         else
Index: /branches/WebJobManager/HeuristicLab.Clients.Hive.WebJobManager/wwwroot/js/hubs/graphhubber.js
===================================================================
--- /branches/WebJobManager/HeuristicLab.Clients.Hive.WebJobManager/wwwroot/js/hubs/graphhubber.js	(revision 13847)
+++ /branches/WebJobManager/HeuristicLab.Clients.Hive.WebJobManager/wwwroot/js/hubs/graphhubber.js	(revision 13848)
@@ -1,1 +1,1 @@
-function autoRefresh(){document.getElementById("refreshtogg").checked&&hubber.server.updateAll()}function restart(a){document.getElementById("restarterbtn"+a).disabled=!0,document.getElementById("restarterbtn"+a).value="Sending restart request...",hubber.server.restartTask(a)}function editJobData(a,b){$("#jobcalculating").html("Calculating: "+a),$("#jobfinished").html("Finished: "+b)}function editTaskData(a,b){if(null!=b.LastHeartbeat){var c=new Date(b.LastHeartbeat);$("#lastupdpar"+a).html("Last update: "+c.toUTCString())}else $("#lastupdpar"+a).html("No updates yet");if(document.getElementById("restarter"+a).style.display="none","0"==b.State)$("#statepar"+a).css({color:"gray","font-weight":"normal"}),$("#statepar"+a).html("State: Offline");else if("1"==b.State)$("#statepar"+a).css({color:"white","font-weight":"normal"}),$("#statepar"+a).html("State: Waiting");else if("2"==b.State)$("#statepar"+a).css({color:"white","font-weight":"normal","text-shadow":"2px 2px black"}),$("#statepar"+a).html("State: Transferring");else if("3"==b.State)$("#statepar"+a).css({color:"white","font-weight":"normal"}),$("#statepar"+a).html("State: Calculating");else if("4"==b.State)$("#statepar"+a).css({color:"white","font-weight":"normal"}),$("#statepar"+a).html("State: Paused"),document.getElementById("restarter"+a).style.display="",document.getElementById("restarterbtn"+a).disabled=!1,document.getElementById("restarterbtn"+a).value="Restart task";else if("5"==b.State){$("#statepar"+a).css({color:"#009900","font-weight":"900","text-shadow":"1px 1px black"}),$("#statepar"+a).html("State: Finished");var d=new Date(b.StateLog[b.StateLog.length-1].DateTime);$("#lastupdpar"+a).html("Finished: "+d.toUTCString())}else"6"==b.State?($("#statepar"+a).css({color:"#e60000","font-weight":"900","text-shadow":"1px 1px black"}),$("#statepar"+a).html("State: Aborted"),document.getElementById("restarter"+a).style.display="",document.getElementById("restarterbtn"+a).disabled=!1,document.getElementById("restarterbtn"+a).value="Restart task"):"7"==b.State&&($("#statepar"+a).css({color:"#e60000","font-weight":"900","text-shadow":"1px 1px black"}),$("#statepar"+a).html("State: Failed"),document.getElementById("restarter"+a).style.display="",document.getElementById("restarterbtn"+a).disabled=!1,document.getElementById("restarterbtn"+a).value="Restart task");$("#executionpar"+a).html(b.ExecutionTime+" executed"),null!=b.StateLog[b.StateLog.length-1].Exception?""!=b.StateLog[b.StateLog.length-1].Exception?($("#exceptionpar"+a).html("Exception: "+b.StateLog[b.StateLog.length-1].Exception),$("#exceptionpar"+a).css({color:"#e60000","font-weight":"700","text-shadow":"1px 1px black"})):"6"==b.State?($("#exceptionpar"+a).html("Task is aborted."),$("#exceptionpar"+a).css({color:"#e65c00","font-weight":"700","text-shadow":"1px 1px black"})):($("#exceptionpar"+a).html("No exceptions"),$("#exceptionpar"+a).css({color:"white","text-shadow":"2px 2px black"})):($("#exceptionpar"+a).html("No exceptions"),$("#exceptionpar"+a).css({color:"white","text-shadow":"2px 2px black"})),$("#statechangespar"+a).html("Statelogs: "+b.StateLog.length);var e=new Date(b.StateLog[0].DateTime),f=new Date(b.StateLog[b.StateLog.length-1].DateTime);$("#graphtitle"+a).html("From "+e.toUTCString()+"<br/> to "+f.toUTCString())}function initSaveData(a,b,c){var d=dataConversion(b,c);d.unshift(a),dataCollection.push(d)}function saveData(a,b,c){for(var d=dataConversion(b,c),e=0;e<dataCollection.length;e++)dataCollection[e][0]==a&&(dataCollection[e][1]=d[0],dataCollection[e][2]=d[1],dataCollection[e][3]=d[2]);redrawGraph(a)}function getDataPie(a){for(var b=0;b<dataCollection.length;b++)if(dataCollection[b][0]==a)return dataCollection[b][2]}function getDataGantt(a){for(var b=0;b<dataCollection.length;b++)if(dataCollection[b][0]==a)return dataCollection[b][3]}function dataConversion(a,b){var c=dataConversionPie(a),d=dataConversionGantt(a,b);return[null,c,d]}function dataConversionGantt(a,b){for(var c=[],d=0;d<a.length;d++){var e={};if(e.startDate=Date.parse(a[d].DateTime),d<a.length-1)e.endDate=Date.parse(a[d+1].DateTime);else{var f=Date.parse(a[d].DateTime);e.endDate=f+6e5,e.last=!0}e.taskName=b,0==a[d].State?e.status="Offline":1==a[d].State?e.status="Waiting":2==a[d].State?e.status="Transferring":3==a[d].State?e.status="Calculating":4==a[d].State?e.status="Paused":5==a[d].State?e.status="Finished":6==a[d].State?e.status="Aborted":7==a[d].State&&(e.status="Failed"),c.push(e)}return[c,b]}function dataConversionPie(a){for(var b=0,c=0,d=0,e=0;e<a.length-1;e++)1==a[e].State?b+=Date.parse(a[e+1].DateTime)-Date.parse(a[e].DateTime):2==a[e].State?c+=Date.parse(a[e+1].DateTime)-Date.parse(a[e].DateTime):3==a[e].State&&(d+=Date.parse(a[e+1].DateTime)-Date.parse(a[e].DateTime));var f=[{values:[Math.round(b/1e3/60),Math.round(c/1e3/60),Math.round(d/1e3/60)],labels:["Minutes waiting","Minutes transferring","Minutes calculating"],type:"pie",marker:{colors:["#f0a742","#80d4ff","#2f6fa6"]}}];return f}function redrawGraph(a){document.getElementById("graph"+a).style.width="100%",document.getElementById("graph"+a).style.height="400px",document.getElementById("graph"+a).innerHTML="",document.getElementById("graph"+a).style.marginLeft="0px",document.getElementById("graphtoggle"+a).checked?setTimeout(function(){var b=getDataGantt(a),c=$("#graph"+a).parent().width()-30;document.getElementById("graph"+a).style.height="300px";var d=d3.gantt().selector("#graph"+a).height("200").width(c).margin({top:20,right:40,bottom:20,left:20}).drawytitles(!1).taskTypes([b[1]]).taskStatus(taskStatus);d(b[0]),document.getElementById("legend"+a).style.display=""},100):(document.getElementById("legend"+a).style.display="none",setTimeout(function(){Plotly.newPlot("graph"+a,getDataPie(a))},100))}function redrawMain(){document.getElementById("graphMain").innerHTML="";for(var a=[],b=[],c=0;c<dataCollection.length;c++){for(var d=dataCollection[c][3][0].slice(),e=d[0].taskName.substring(0,5)+" | "+(c+1),f=0;f<d.length;f++)d[f].taskName=e;a=a.concat(d),b=b.concat(e)}var g=20*b.length+100;document.getElementById("graphMain").style.height=g+"px";var h=$("#graphMain").parent().width()-100,i=d3.gantt().selector("#graphMain").height(g-50).width(h).taskTypes(b).taskStatus(taskStatus);document.getElementById("graphMain").style.marginLeft="20px",i(a)}var hubber=$.connection.jobUpdaterHub;$(function(){var a=document.getElementById("userId").innerHTML;$.connection.hub.qs={userid:a},$.connection.hub.start().done(function(){hubber.server.initConnection(),redrawMain()}),hubber.client.processData=function(a,b,c){var d=JSON.parse(b);editTaskData(a,d),saveData(a,d.StateLog,c),console.log("#UPDATED "+a)},hubber.client.processJobData=function(a,b){editJobData(a,b)},hubber.client.requestDone=function(){document.getElementById("refreshtogg").checked&&setTimeout(function(){hubber.server.updateAll(),console.log("#REFRESH ALL")},5e3)}});var dataCollection=[],taskStatus={Offline:"bar-off",Waiting:"bar-wait",Transferring:"bar-trans",Calculating:"bar-calc",Paused:"bar-paus",Finished:"bar-fin",Aborted:"bar-abo",Failed:"bar-fail"};
+function autoRefresh(){document.getElementById("refreshtogg").checked&&hubber.server.updateAll()}function restart(a){document.getElementById("restarterbtn"+a).disabled=!0,document.getElementById("restarterbtn"+a).value="Sending restart request...",hubber.server.restartTask(a)}function editJobData(a,b){$("#jobcalculating").html("Calculating: "+a),$("#jobfinished").html("Finished: "+b)}function editTaskData(a,b){if(null!=b.LastHeartbeat){var c=new Date(b.LastHeartbeat);$("#lastupdpar"+a).html("Last update: "+c.toUTCString())}else $("#lastupdpar"+a).html("No updates yet");if(document.getElementById("restarter"+a).style.display="none","0"==b.State)$("#statepar"+a).css({color:"gray","font-weight":"normal"}),$("#statepar"+a).html("State: Offline");else if("1"==b.State)$("#statepar"+a).css({color:"white","font-weight":"normal"}),$("#statepar"+a).html("State: Waiting");else if("2"==b.State)$("#statepar"+a).css({color:"white","font-weight":"normal","text-shadow":"2px 2px black"}),$("#statepar"+a).html("State: Transferring");else if("3"==b.State)$("#statepar"+a).css({color:"white","font-weight":"normal"}),$("#statepar"+a).html("State: Calculating");else if("4"==b.State)$("#statepar"+a).css({color:"white","font-weight":"normal"}),$("#statepar"+a).html("State: Paused"),document.getElementById("restarter"+a).style.display="",document.getElementById("restarterbtn"+a).disabled=!1,document.getElementById("restarterbtn"+a).value="Restart task";else if("5"==b.State){$("#statepar"+a).css({color:"#009900","font-weight":"900","text-shadow":"1px 1px black"}),$("#statepar"+a).html("State: Finished");var d=new Date(b.StateLog[b.StateLog.length-1].DateTime);$("#lastupdpar"+a).html("Finished: "+d.toUTCString())}else"6"==b.State?($("#statepar"+a).css({color:"#e60000","font-weight":"900","text-shadow":"1px 1px black"}),$("#statepar"+a).html("State: Aborted"),document.getElementById("restarter"+a).style.display="",document.getElementById("restarterbtn"+a).disabled=!1,document.getElementById("restarterbtn"+a).value="Restart task"):"7"==b.State&&($("#statepar"+a).css({color:"#e60000","font-weight":"900","text-shadow":"1px 1px black"}),$("#statepar"+a).html("State: Failed"),document.getElementById("restarter"+a).style.display="",document.getElementById("restarterbtn"+a).disabled=!1,document.getElementById("restarterbtn"+a).value="Restart task");$("#executionpar"+a).html(b.ExecutionTime+" executed"),null!=b.StateLog[b.StateLog.length-1].Exception?""!=b.StateLog[b.StateLog.length-1].Exception?($("#exceptionpar"+a).html("Exception: "+b.StateLog[b.StateLog.length-1].Exception),$("#exceptionpar"+a).css({color:"#e60000","font-weight":"700","text-shadow":"1px 1px black"})):"6"==b.State?($("#exceptionpar"+a).html("Task is aborted."),$("#exceptionpar"+a).css({color:"#e65c00","font-weight":"700","text-shadow":"1px 1px black"})):($("#exceptionpar"+a).html("No exceptions"),$("#exceptionpar"+a).css({color:"white","text-shadow":"2px 2px black"})):($("#exceptionpar"+a).html("No exceptions"),$("#exceptionpar"+a).css({color:"white","text-shadow":"2px 2px black"})),$("#statechangespar"+a).html("Statelogs: "+b.StateLog.length);var e=new Date(b.StateLog[0].DateTime),f=new Date(b.StateLog[b.StateLog.length-1].DateTime);$("#graphtitle"+a).html("From "+e.toUTCString()+"<br/> to "+f.toUTCString())}function initSaveData(a,b,c){var d=dataConversion(b,c);d.unshift(a),dataCollection.push(d)}function saveData(a,b,c){for(var d=dataConversion(b,c),e=0;e<dataCollection.length;e++)dataCollection[e][0]==a&&(dataCollection[e][1]=d[0],dataCollection[e][2]=d[1],dataCollection[e][3]=d[2]);redrawGraph(a)}function getDataPie(a){for(var b=0;b<dataCollection.length;b++)if(dataCollection[b][0]==a)return dataCollection[b][2]}function getDataGantt(a){for(var b=0;b<dataCollection.length;b++)if(dataCollection[b][0]==a)return dataCollection[b][3]}function dataConversion(a,b){var c=dataConversionPie(a),d=dataConversionGantt(a,b);return[null,c,d]}function dataConversionGantt(a,b){for(var c=[],d=0;d<a.length;d++){var e={};if(e.startDate=Date.parse(a[d].DateTime),d<a.length-1)e.endDate=Date.parse(a[d+1].DateTime);else{var f=Date.parse(a[d].DateTime);e.endDate=f+6e5,e.last=!0}e.taskName=b,0==a[d].State?e.status="Offline":1==a[d].State?e.status="Waiting":2==a[d].State?e.status="Transferring":3==a[d].State?e.status="Calculating":4==a[d].State?e.status="Paused":5==a[d].State?e.status="Finished":6==a[d].State?e.status="Aborted":7==a[d].State&&(e.status="Failed"),c.push(e)}return[c,b]}function dataConversionPie(a){for(var b=0,c=0,d=0,e=0;e<a.length-1;e++)1==a[e].State?b+=Date.parse(a[e+1].DateTime)-Date.parse(a[e].DateTime):2==a[e].State?c+=Date.parse(a[e+1].DateTime)-Date.parse(a[e].DateTime):3==a[e].State&&(d+=Date.parse(a[e+1].DateTime)-Date.parse(a[e].DateTime));var f=[{values:[Math.round(b/1e3/60),Math.round(c/1e3/60),Math.round(d/1e3/60)],labels:["Minutes waiting","Minutes transferring","Minutes calculating"],type:"pie",marker:{colors:["#f0a742","#80d4ff","#2f6fa6"]}}];return f}function redrawGraph(a){document.getElementById("graph"+a).style.width="100%",document.getElementById("graph"+a).style.height="400px",document.getElementById("graph"+a).innerHTML="",document.getElementById("graph"+a).style.marginLeft="0px",document.getElementById("graphtoggle"+a).checked?setTimeout(function(){var b=getDataGantt(a),c=$("#graph"+a).parent().width()-30;document.getElementById("graph"+a).style.height="300px";var d=d3.gantt().selector("#graph"+a).height("200").width(c).margin({top:20,right:40,bottom:20,left:20}).drawytitles(!1).taskTypes([b[1]]).taskStatus(taskStatus);d(b[0]),document.getElementById("legend"+a).style.display=""},100):(document.getElementById("legend"+a).style.display="none",setTimeout(function(){Plotly.newPlot("graph"+a,getDataPie(a))},100))}function redrawMain(){document.getElementById("graphMain").innerHTML="";for(var a=[],b=[],c=0;c<dataCollection.length;c++){for(var d=dataCollection[c][3][0].slice(),e=d[0].taskName.substring(0,5)+" | "+(c+1),f=0;f<d.length;f++)d[f].taskName=e;a=a.concat(d),b=b.concat(e)}var g=20*b.length+100;document.getElementById("graphMain").style.height=g+"px";var h=$("#graphMain").parent().width()-100,i=d3.gantt().selector("#graphMain").height(g-50).width(h).taskTypes(b).taskStatus(taskStatus);document.getElementById("graphMain").style.marginLeft="20px",i(a)}var hubber=$.connection.jobUpdaterHub;$(function(){var a=document.getElementById("userId").innerHTML;$.connection.hub.qs={userid:a},$.connection.hub.start().done(function(){hubber.server.initConnection(),redrawMain()}),hubber.client.processData=function(a,b,c){var d=JSON.parse(b);editTaskData(a,d),saveData(a,d.StateLog,c),console.log("#UPDATED "+a)},hubber.client.processJobData=function(a,b){editJobData(a,b)},hubber.client.requestDone=function(){document.getElementById("refreshtogg").checked&&setTimeout(function(){hubber.server.updateAll(),console.log("#REFRESH ALL")},5e3+500*dataCollection.length)}});var dataCollection=[],taskStatus={Offline:"bar-off",Waiting:"bar-wait",Transferring:"bar-trans",Calculating:"bar-calc",Paused:"bar-paus",Finished:"bar-fin",Aborted:"bar-abo",Failed:"bar-fail"};
