Changeset 13805


Ignore:
Timestamp:
04/27/16 16:48:35 (5 years ago)
Author:
jlodewyc
Message:

#2582 Bugfixing, email setup password and code commenting

Location:
branches/WebJobManager/HeuristicLab.Clients.Hive.WebJobManager
Files:
18 edited

Legend:

Unmodified
Added
Removed
  • branches/WebJobManager/HeuristicLab.Clients.Hive.WebJobManager/Controllers/HomeController.cs

    r13741 r13805  
    9393            }
    9494        }
     95        /// <summary>
     96        /// Redirect user to home sceen for a full logout
     97        /// </summary>
     98        /// <returns></returns>
    9599        public IActionResult Logout()
    96100        {
  • branches/WebJobManager/HeuristicLab.Clients.Hive.WebJobManager/Controllers/ResourceController.cs

    r13782 r13805  
    1414namespace HeuristicLab.Clients.Hive.WebJobManager.Controllers
    1515{
     16    /// <summary>
     17    /// Controller for the resources. Only handles requests that refresh the page.
     18    /// </summary>
    1619    public class ResourceController : Controller
    1720    {
     
    2932            _environment = env;
    3033        }
     34        /// <summary>
     35        /// Initialize and check the login. Gets all the required services for the user. 
     36        /// </summary>
     37        /// <returns></returns>
    3138        private bool init()
    3239        {
     
    4653            }
    4754        }
     55        /// <summary>
     56        /// Loads the main page for the resources
     57        /// </summary>
     58        /// <returns></returns>
    4859        public IActionResult Index()
    4960        {
     
    6071            }
    6172        }
     73        /// <summary>
     74        /// Changes the parent for a specfic resource
     75        /// </summary>
     76        /// <param name="inpid">Resource to edit</param>
     77        /// <param name="inpidpar">New parent resource</param>
     78        /// <returns></returns>
    6279        [HttpPost]
    6380        public IActionResult changeParent(string inpid, string inpidpar)
     
    7087                adminClient.Refresh();
    7188                var tochange = adminClient.Resources.ToList().Find(x => x.Id == gid);
    72                
     89                //gets current resource
    7390                if (inpidpar != null && inpidpar != "") {
    7491                    Guid tempid = Guid.Parse(inpidpar);
    75                     while (tempid != null)
    76                     {
     92                    while (tempid != null && tempid != Guid.Empty)
     93                    {//Check if a loop could occur (some parent of the parent being the parent)
    7794                        if (tempid != gid)
    78                         {
    79                             tempid = (Guid)adminClient.Resources.ToList().Find(x => x.Id == tempid).ParentResourceId;
     95                        {//Not equal so move up a level
     96                            var t = adminClient.Resources.ToList().Find(x => x.Id == tempid);
     97                            if (t.ParentResourceId == null)
     98                                tempid = Guid.Empty;
     99                            else
     100                                tempid = (Guid)t.ParentResourceId;
     101
    80102                        }
    81103                        else
    82                             break;
    83                     }
    84                     if(tempid == null)
     104                            break; //breaks loop if equal
     105                    }
     106                    if(tempid == null || tempid == Guid.Empty)//Broken loop => the tempid is not empty so no change
    85107                        tochange.ParentResourceId = Guid.Parse(inpidpar);
    86108                }
     
    88110                    tochange.ParentResourceId = null;
    89111                adminClient.Store(tochange, CancellationToken.None);
    90 
    91                 return RedirectToAction("Index", "Resource");
    92             }
    93             else
    94             {
    95                 return RedirectToAction("Index", "Home");
    96             }
    97         }
     112                //Save to server
     113
     114                return RedirectToAction("Index", "Resource");
     115            }
     116            else
     117            {
     118                return RedirectToAction("Index", "Home");
     119            }
     120        }
     121        /// <summary>
     122        /// Adds recources to a resource group
     123        /// </summary>
     124        /// <param name="addres">Array containing all the resources ID's from the group</param>
     125        /// <param name="groupid">Group id</param>
     126        /// <returns></returns>
     127        [HttpPost]
     128        public IActionResult addResourcesToGroup(string[] addres, string groupid)
     129        {
     130            if (init())
     131            {
     132                Guid gid = Guid.Parse(groupid);
     133                adminClient.Refresh();
     134                var exist = adminClient.Resources.ToList().FindAll(x => x.ParentResourceId == gid);
     135                //Current existing member of the group
     136
     137                foreach(var a in addres)
     138                {//loop on each ID
     139                    Guid tempid = Guid.Parse(a);
     140                    var elemid = exist.FindIndex(x => x.Id == tempid);
     141                    if (elemid != -1)
     142                    {//If element already is a member of the group: scramble temporary ID (for future reference)
     143                        exist[elemid].Id = Guid.Empty;
     144                    }
     145                    else
     146                    {//If element is not yet in list => change parentresourceid from that element
     147                        var obj = adminClient.Resources.ToList().Find(x => x.Id == tempid);
     148                        obj.ParentResourceId = gid;
     149                        adminClient.Store(obj, CancellationToken.None);
     150                    }
     151                }
     152                foreach(var e in exist)
     153                {//Loop on existing and check the ID's
     154                    if(e.Id != Guid.Empty)
     155                    {//ID != Empty means that element should not be a member of the list anymore
     156                        e.ParentResourceId = null; //remove ParentResourceID from element
     157                        adminClient.Store(e, CancellationToken.None);
     158                    }
     159                }
     160
     161                return RedirectToAction("Index", "Resource");
     162
     163            }
     164            else
     165            {
     166                return RedirectToAction("Index", "Home");
     167            }
     168        }
     169        /// <summary>
     170        /// Delete a client group (relinks the parent from every member to possible grandparent)
     171        /// </summary>
     172        /// <param name="inpid">Group ID to delete</param>
     173        /// <returns></returns>
    98174        [HttpPost]
    99175        public IActionResult deleteClientGroup(string inpid)
     
    105181                adminClient.Refresh();
    106182                var group = adminClient.Resources.ToList().Find(x => x.Id == gid);
     183                //Group to delete
    107184                var list = adminClient.Resources.ToList().FindAll(x => x.ParentResourceId == gid);
     185                //All members from the group
    108186                foreach(var cl in list)
    109                 {
     187                {//Links parent from every child to parent from the group to delete.
    110188                    cl.ParentResourceId = group.ParentResourceId;
    111189                    adminClient.Store(cl, CancellationToken.None);
     
    120198            }
    121199        }
    122 
     200        /// <summary>
     201        /// Create a new Client Group
     202        /// </summary>
     203        /// <param name="inpname">Name for the group</param>
     204        /// <param name="inpheart">Heartbeat</param>
     205        /// <param name="inpparent">Possible parent for the group</param>
     206        /// <param name="clientstoadd">Clients to be added to the group</param>
     207        /// <returns></returns>
    123208        [HttpPost]
    124209        public IActionResult newClientGroup(string inpname, int inpheart, string inpparent, string[] clientstoadd)
     
    128213
    129214                SlaveGroup sg = new SlaveGroup();
     215                //init
    130216                sg.Id = Guid.Empty;
    131217                sg.Name = inpname;
    132218                sg.HbInterval = inpheart;
    133                 if (inpparent != "")
     219                if (inpparent != null)
    134220                    sg.ParentResourceId = Guid.Parse(inpparent);
     221
    135222                sg.OwnerUserId = serviceLocator.getHiveServiceClient().GetUserIdByUsername(serviceLocator.getHiveServiceClient().ClientCredentials.UserName.UserName);
    136223                adminClient.Store(sg, CancellationToken.None);
    137224                adminClient.Refresh();
     225                //Reloads the resources
    138226                var id = adminClient.Resources.ToList().Find(x => x.Name == inpname).Id;
    139227                foreach(var s in clientstoadd)
    140                 {
     228                {//Loop so each client can be added to the group
    141229                    var cid = Guid.Parse(s);
    142230                    var client = adminClient.Resources.ToList().Find(x => x.Id == cid);
  • branches/WebJobManager/HeuristicLab.Clients.Hive.WebJobManager/Controllers/UserController.cs

    r13754 r13805  
    88using System.Collections.Generic;
    99using System.Linq;
     10using System.Net.Mail;
    1011using System.ServiceModel.Security;
    1112using System.Threading.Tasks;
     
    1314namespace HeuristicLab.Clients.Hive.WebJobManager.Controllers
    1415{
     16    /// <summary>
     17    /// Handles all the actions for user management
     18    /// </summary>
    1519    public class UserController : Controller
    1620    {
     
    2731            _environment = env;
    2832        }
     33        /// <summary>
     34        /// Init required services and checks login
     35        /// </summary>
     36        /// <returns></returns>
    2937        private bool init()
    3038        {
     
    4452        }
    4553        #region Users
    46 
     54        /// <summary>
     55        /// Show users page
     56        /// </summary>
     57        /// <returns></returns>
    4758        public IActionResult Index()
    4859        {
     
    5162                ViewBag.Title = "Users";
    5263                UserViewModel vm = new UserViewModel(accessClient).refreshAll() ;
     64                //Refreshall for users, groups and roles
    5365                ViewBag.SessionId = HttpContext.Session.GetString("UserId");
    5466                return View("Index", vm);
     
    6274        public IActionResult SelectUser(string id)
    6375        {
    64             ;
    6576            if (init())
    6677            {
     
    6980                UserViewModel vm = new UserViewModel(accessClient).refreshAll();
    7081                if (curr == Guid.Empty)
    71                 {
     82                {//new user
    7283                    ViewBag.Title = "Add User";
    7384                }
    7485                else
    75                 {
     86                {//View an existing user
    7687                    vm.SelectedUser = vm.getUserById(curr);
    7788                    vm.SelectedUserSubscriptions = accessClient.getSubscribedGroups(curr);
     
    8293                ViewBag.SessionId = HttpContext.Session.GetString("UserId");
    8394                return View("Index", vm);
    84             }
    85             else
    86             {
    87                 return RedirectToAction("Index", "Home");
    88             }
    89         }
     95                //Uses Index page too, with the additional info in the Viewmodel
     96            }
     97            else
     98            {
     99                return RedirectToAction("Index", "Home");
     100            }
     101        }
     102        /// <summary>
     103        /// Saves an existing user or adds a new user
     104        /// </summary>
     105        /// <param name="inpusername">Username</param>
     106        /// <param name="inpfullname">Full name </param>
     107        /// <param name="inpemail">Email</param>
     108        /// <param name="u">User ID</param>
     109        /// <param name="rolestoadd">Roles to add to the user</param>
     110        /// <param name="groupstoadd">Groups to subscribe the user to</param>
     111        /// <returns></returns>
    90112        [HttpPost]
    91113        public IActionResult saveUser(string inpusername, string inpfullname, string inpemail, string u, string[] rolestoadd, string[] groupstoadd)
     
    96118                var uid = Guid.Parse(u);
    97119                Access.User user;
    98                 if (uid == Guid.Empty)
     120                if (uid == Guid.Empty)//checks if user is new or exists
    99121                    user = new Access.User();
    100122                else
     
    107129
    108130                if (uid == Guid.Empty)
    109                 {
     131                {//New user
    110132                    user.UserName = inpusername;
    111133                    uid = accessClient.addUser(user);
     134                    var newpass = accessClient.resetPassword(uid);
     135                    sendPassmail(accessClient.Users.Find(x => x.Id == uid), newpass);
     136                    //password received through mail
    112137                    ViewBag.Title = user.UserName + " added - User";
    113138                }
    114139                else
    115                 {
     140                {//Existing user
    116141                    accessClient.updateUser(user);
    117142                    ViewBag.Title = user.UserName + " updated - User";
    118143                }
    119                 accessClient.RefreshUsers();
     144                accessClient.RefreshUsers();//Refresh data from user
    120145                user = accessClient.Users.Find(x => x.Id == uid);
    121146                foreach (var s in rolestoadd)
    122                 {
     147                {//Loop to add roles
    123148                    var role = accessClient.Roles.Find(x => x.Name == s);
    124149
     
    127152                accessClient.RefreshUserGroups();
    128153                foreach(var g in groupstoadd)
    129                 {
     154                {//loop to subscribe to groups
    130155                    var gid = Guid.Parse(g);
    131156                    var group = accessClient.Groups.Find(x => x.Id == gid);
     
    140165
    141166        }
     167        /// <summary>
     168        /// Sends email for a specific user, containg a password
     169        /// </summary>
     170        /// <param name="u">User to mail</param>
     171        /// <param name="pass">Password to send</param>
     172        public static void sendPassmail(Access.User u, string pass)
     173        {/*
     174            SmtpClient smtpClient = new SmtpClient("mail.MyWebsiteDomainName.com", 25);
     175
     176            smtpClient.Credentials = new System.Net.NetworkCredential("info@MyWebsiteDomainName.com", "myIDPassword");
     177            smtpClient.UseDefaultCredentials = true;
     178            smtpClient.DeliveryMethod = SmtpDeliveryMethod.Network;
     179            smtpClient.EnableSsl = true;
     180            MailMessage mail = new MailMessage();
     181
     182            //Setting From , To and CC
     183            mail.From = new MailAddress("info@MyWebsiteDomainName", "MyWeb Site");
     184            mail.Subject = "Password changed - HeuristicLab Hive";
     185            mail.Body = "Hello " + u.FullName + ", " +
     186                "Your password was changed through the HeuristicLab Hive web application." +
     187                "The new password for " + u.UserName + " is '" + pass + "'.";
     188            mail.To.Add(new MailAddress(u.Email));
     189
     190            smtpClient.Send(mail);
     191            */
     192        }
     193        /// <summary>
     194        /// Delete a user
     195        /// </summary>
     196        /// <param name="id">User ID to delete</param>
     197        /// <returns></returns>
    142198        public IActionResult deleteUser(string id)
    143199        {
     
    148204
    149205                if (uid == Guid.Empty)
    150                 {
     206                {//check for empty Guid, should not happen but still
    151207                    vm.message = "Something went wrong, user is not deleted";
    152208                    return View("Index", vm);
     
    157213                    vm.message = user.UserName + " (" + user.FullName + ") has been deleted";
    158214                    accessClient.DeleteUser(user);
    159                     vm.refreshAll();
     215                    vm.refreshAll();//refreshAll for index view
    160216                    ViewBag.Title = "Users";
    161                     return View("Index", vm);
    162                 }
    163             }
    164             else
    165             {
    166                 return RedirectToAction("Index", "Home");
    167             }
    168 
    169         }
    170 
     217                    return View("Index", vm);//No redirect to save the viewbag message
     218                }
     219            }
     220            else
     221            {
     222                return RedirectToAction("Index", "Home");
     223            }
     224
     225        }
     226        /// <summary>
     227        /// Deletes a role from a user
     228        /// </summary>
     229        /// <param name="id">User Id</param>
     230        /// <param name="role">Role name</param>
     231        /// <returns></returns>
    171232        public IActionResult deleteUserRole(string id, string role)
    172233        {
     
    178239                var user = vm.getUserById(uid);
    179240                var r = vm.getRoleByName(role);
     241
    180242                accessClient.deleteUserRole(user, r);
    181243                return RedirectToAction("SelectUser", new { id = id });
     
    186248            }
    187249        }
     250        /// <summary>
     251        /// Delete user from a group
     252        /// </summary>
     253        /// <param name="id">User Id</param>
     254        /// <param name="group">Group Id</param>
     255        /// <returns></returns>
    188256        public IActionResult deleteUserGroup(string id, string group)
    189257        {
     
    196264                var user = vm.getUserById(mid);
    197265                var gr = vm.getGroupById(gid);
     266               
    198267                accessClient.deleteMember(user, gr);
    199268                return RedirectToAction("SelectUser", new { id = id});
     
    208277
    209278        #region Groups
     279        /// <summary>
     280        /// Shows the groups overview, opening up with "Add group"
     281        /// </summary>
     282        /// <returns></returns>
    210283        public IActionResult Groups()
    211284        {
     
    222295            }
    223296        }
     297        /// <summary>
     298        /// Show information for a specific group (Guid.empty = new group)
     299        /// </summary>
     300        /// <param name="id">Group ID</param>
     301        /// <returns></returns>
    224302        public IActionResult SelectGroup(string id)
    225303        {
     
    232310                    .refreshUsers();
    233311                if (curr == Guid.Empty)
    234                 {
     312                {//Add group
    235313                    ViewBag.Title = "Add group";
    236314                }
    237315                else
    238                 {
     316                {//Show existing group info and possibility to edit
    239317                    vm.SelectedGroup = vm.getGroupById(curr);
    240318                    vm.SelectedGroupMembers = accessClient.getGroupMembers(curr);
     
    249327            }
    250328        }
     329        /// <summary>
     330        /// Saves an exisiting group or adds a new one.
     331        /// </summary>
     332        /// <param name="inpgroupname">Group name</param>
     333        /// <param name="u">Group id (empty for new)</param>
     334        /// <param name="userstoadd">Users to add to group</param>
     335        /// <param name="groupstoadd">Groups to add to group</param>
     336        /// <returns></returns>
    251337        [HttpPost]
    252338        public IActionResult saveGroup(string inpgroupname, string u, string[] userstoadd, string[] groupstoadd)
     
    259345                Access.UserGroup group;
    260346
     347                if (uid == Guid.Empty)//Create new group
     348                    group = new Access.UserGroup();
     349                else//Find existing group
     350                    group = accessClient.Groups.Find(x => x.Id == uid);
     351
     352                group.Name = inpgroupname;
     353
    261354                if (uid == Guid.Empty)
    262                     group = new Access.UserGroup();
    263                 else
    264                     group = accessClient.Groups.Find(x => x.Id == uid);
    265 
    266                 group.Name = inpgroupname;
    267 
    268                 if (uid == Guid.Empty)
    269                 {
     355                {//New Group add
    270356                    uid = accessClient.addGroup(group);
    271357                    ViewBag.Title = group.Name + " added - Group";
    272358                }
    273359                else
    274                 {
     360                {//Existing group update
    275361                    accessClient.updateGroup(group);
    276362                    ViewBag.Title = group.Name + " updated - Group";
     
    278364                vm.refreshGroups();
    279365                group = vm.getGroupById(uid);
     366                //refresh group info
    280367                foreach (var s in userstoadd)
    281                 {
     368                {//Subscribes members to group
    282369                    var tempid = Guid.Parse(s);
    283370                    var member = vm.getUserById(tempid);
     
    285372                }
    286373                foreach (var g in groupstoadd)
    287                 {
     374                {//Subscribes groups to group
    288375                    var tempid = Guid.Parse(g);
    289376                    var member = vm.getGroupById(tempid);
     
    298385            }
    299386        }
     387        /// <summary>
     388        /// Delete an existing group
     389        /// </summary>
     390        /// <param name="id">Group to delete</param>
     391        /// <returns></returns>
    300392        public IActionResult deleteGroup(string id)
    301393        {
     
    306398
    307399                if (uid == Guid.Empty)
    308                 {
     400                {//Check for empty ID, should not happen but still..
    309401                    vm.message = "Something went wrong, group is not deleted";
    310402                    return View("Groups", vm);
    311403                }
    312404                else
    313                 {
     405                {//Deletes the user group
    314406                    var group = vm.getGroupById(uid);
    315407                    vm.message = group.Name + " has been deleted";
     
    325417
    326418        }
     419        /// <summary>
     420        /// Delete a member from a group 
     421        /// </summary>
     422        /// <param name="g">Group id</param>
     423        /// <param name="m">User id</param>
     424        /// <returns>Group selected</returns>
    327425        public IActionResult deleteMember(string g, string m)
    328426        {
     
    334432
    335433                if (gid == Guid.Empty || mid == Guid.Empty)
    336                 {
     434                {//Should not be empty but still..
    337435                    vm.message = "Something went wrong, member is not deleted";
    338436                    return View("Groups", vm);
    339437                }
    340438                else
    341                 {
     439                {//Deletes the member
    342440                    var group = vm.getGroupById(gid);
    343441                    Access.UserGroupBase member = vm.getUserById(mid);
     
    361459
    362460        #region Roles
     461        /// <summary>
     462        /// Shows roles overview, opening with "Add role"
     463        /// </summary>
     464        /// <returns></returns>
    363465        public IActionResult Roles()
    364466        {
     
    376478            }
    377479        }
     480        /// <summary>
     481        /// Shows information for a specific role
     482        /// </summary>
     483        /// <param name="name">Role name</param>
     484        /// <returns></returns>
    378485        public IActionResult SelectRole(string name)
    379486        {
     
    383490                UserViewModel vm = new UserViewModel(accessClient).refreshRoles();
    384491                if (name == "" || name == null)
    385                 {
     492                {//Add role
    386493                    ViewBag.Title = "Add Role";
    387494                }
    388495                else
    389                 {
     496                {//Edit/view role
    390497                    vm.SelectedRole = vm.getRoleByName(name);
    391498                    vm.SelectedRoleEnrolled = accessClient.getEnrolled(vm.SelectedRole);
     
    401508            }
    402509        }
     510        /// <summary>
     511        /// Saves a role or adds a new one
     512        /// </summary>
     513        /// <param name="inprolename">Role name</param>
     514        /// <returns></returns>
    403515        [HttpPost]
    404516        public IActionResult saveRole(string inprolename)
     
    422534            }
    423535        }
     536        /// <summary>
     537        /// Delete a role
     538        /// </summary>
     539        /// <param name="name">Role name</param>
     540        /// <returns></returns>
    424541        public IActionResult deleteRole(string name)
    425542        {
     
    434551            }
    435552        }
     553        /// <summary>
     554        /// Deletes a user from a role
     555        /// </summary>
     556        /// <param name="id">User id</param>
     557        /// <param name="role">Role name</param>
     558        /// <returns></returns>
    436559        public IActionResult deleteRoleUser(string id, string role)
    437560        {
  • branches/WebJobManager/HeuristicLab.Clients.Hive.WebJobManager/Hubs/CalendarHub.cs

    r13795 r13805  
    1212namespace HeuristicLab.Clients.Hive.WebJobManager.Hubs
    1313{
     14    /// <summary>
     15    /// SignalR Hub that manages all resource management.
     16    /// </summary>
    1417    public class CalendarHub : Hub
    1518    {
     
    1922        private HiveServiceLocatorWeb servloc;
    2023        private AccessAdministrationClient accessClient;
     24        /// <summary>
     25        /// Loads up the services for the client (Instance is only created upon a call from a client)
     26        /// </summary>
    2127        private void loader()
    2228        {
     
    3541            }
    3642        }
     43        /// <summary>
     44        /// Initial client request for all user, group and resource information
     45        /// </summary>
    3746        public void requestInfo()
    3847        {
     
    4049            adminClient.Refresh();
    4150            UserViewModel vm = new UserViewModel(accessClient).refreshAll();
     51
    4252            var users = JsonConvert.SerializeObject(vm.users);
    4353            var groups = JsonConvert.SerializeObject(vm.ugroups);
     
    4555            Clients.Caller.processData(res, users, groups);
    4656        }
     57        /// <summary>
     58        /// Request for the downtimes of a specific resource
     59        /// </summary>
     60        /// <param name="id">Resource ID</param>
    4761        public void requestDownTime(string id)
    4862        {
     
    5064            adminClient.Refresh();
    5165            Guid t = Guid.Parse(id);
     66
     67            //Loads up the downtimes for the set resource ID
    5268            adminClient.DowntimeForResourceId = t;
    5369            adminClient.RefreshCalendar();
     70           
    5471            var down = JsonConvert.SerializeObject(adminClient.Downtimes);
    5572            Clients.Caller.processDowntime(id, down);
    5673        }
     74        /// <summary>
     75        /// Request for permissions of a specific resource (refreshable by recall)
     76        /// </summary>
     77        /// <param name="id">Resource ID</param>
    5778        public void requestPermissions(string id)
    5879        {
     
    6384        }
    6485
     86        /// <summary>
     87        /// Edit permissions for a resource
     88        /// </summary>
     89        /// <param name="perms">Permissions ID's</param>
     90        /// <param name="idresource">Resource ID</param>
    6591        public void changePermissions(string[] perms, string idresource)
    6692        {
    6793            loader();
    6894            var res = Guid.Parse(idresource);
     95
     96            //Collect current permissions
    6997            var exist = servloc.CallHiveService(x => x.GetResourcePermissions(res));
     98
     99            //Separate list for new and to remove permissions
    70100            List<Guid> newPerms = new List<Guid>();
    71101            List<Guid> revokePerms = new List<Guid>();
     102
    72103            for (var i = 0; i < perms.Length; i++)
    73104            {
     
    75106                var elemid = exist.FindIndex(x => x.GrantedUserId == p);
    76107                if (elemid != -1)
    77                 {
     108                {//If it already exists => Scramble up Guid (checked further)
    78109                    exist[elemid].GrantedUserId = Guid.Empty;
    79110                }
    80111                else
    81                 {
     112                {//If it's not in the list, add to new permissions
    82113                    newPerms.Add(p);
    83114                }
    84115            }
     116            //Adds the new permissions to the resource
    85117            servloc.CallHiveService(x => x.GrantResourcePermissions(res, newPerms));
    86118            foreach (var ex in exist)
    87             {
     119            {//Checks for intact ID's and adds them to the revoke list
    88120                if(ex.GrantedUserId != Guid.Empty)
    89121                {
     
    91123                }
    92124            }
     125            //Revokes all permissions that were deselected by the user
    93126            servloc.CallHiveService(x => x.RevokeResourcePermissions(res, revokePerms));
     127            //Live reload the view for the resource
    94128            requestPermissions(idresource);
    95129        }
     130        /// <summary>
     131        /// Toggles the disposable setting for a resource
     132        /// </summary>
     133        /// <param name="id">Resource ID</param>
    96134        public void toggleDisposable(string id)
    97135        {
     
    100138            Guid c = Guid.Parse(id);
    101139            var obj = adminClient.Resources.ToList().Find(x => x.Id == c);
     140
     141            //Toggle
    102142            ((Slave)(obj)).IsDisposable = !((Slave)(obj)).IsDisposable;
     143
    103144            adminClient.Store(obj, CancellationToken.None);
     145
     146            //Notify client of successful saving
    104147            Clients.Caller.processDispose( ((Slave)(obj)).IsDisposable);
    105148
    106149        }
     150        /// <summary>
     151        /// Saves changes to a resource calendar
     152        /// </summary>
     153        /// <param name="id">Resource id</param>
     154        /// <param name="del">To delete downtimes</param>
     155        /// <param name="add">New downtimes</param>
     156        /// <param name="upd">Downtimes to update</param>
     157        /// <param name="fresh">Check if refresh should be sent (Save all current graph or Save current graph)</param>
     158        /// <param name="last">Check for last request (Save all)</param>
    107159        public void saveCalendar(string id, string[] del, string[][] add, string[][] upd, bool fresh, bool last)
    108160        {
    109161            loader();
    110162            var calid = Guid.Parse(id);
     163           
     164            //Load up calendar
    111165            adminClient.Refresh();
    112166            adminClient.DowntimeForResourceId = calid;
    113167            adminClient.RefreshCalendar();
     168
    114169            var downlist = adminClient.Downtimes.ToList();
    115170            foreach(var s in del)
    116             {
     171            {//Deletes downtimes
    117172                var gu = Guid.Parse(s);
    118173                var el = downlist.Find(x => x.Id == gu);
     
    120175            }
    121176            foreach (var s in add)
    122             {
     177            {//Adds new downtimes
     178                //init
    123179                var obj = new Downtime();
    124180                obj.Id = Guid.Empty;
     
    134190                    obj.AllDayEvent = false;
    135191                obj.ResourceId = Guid.Parse(s[4]);
     192
     193                //Recurrency check
    136194                if (s[5] == "true")
    137                 {
     195                {//Recurrency set
    138196                    obj.Recurring = true;
    139197                    if (s[6] == "0")
    140                     {
     198                    {//new Recur
    141199                        var dayarr = s[9].Split(',');
    142200                        var start = (new DateTime(1970, 1, 1)).AddMilliseconds(double.Parse(s[7]));
    143201                        var end = (new DateTime(1970, 1, 1)).AddMilliseconds(double.Parse(s[8]));
    144                         loopAddDowns(start, end, dayarr, obj);   
     202                        loopAddDowns(start, end, dayarr, obj);//Loop creation of recurrency. Start to end date
    145203                    }
    146204                    else
    147                     {
     205                    {//Existing recurrency (only edits current element, client handles the creation of the other events)
    148206                        obj.RecurringId = Guid.Parse(s[6]);
    149207                        adminClient.Store(obj, CancellationToken.None);
    150208                    }
    151209                }
    152                 else {
     210                else { //No recurrency
    153211                    obj.Recurring = false;
    154212                    adminClient.Store(obj, CancellationToken.None);
     
    158216            }
    159217            foreach(var s in upd)
    160             {
     218            {//Update existing downtime
    161219                 var obj = downlist.Find(x => x.Id == Guid.Parse(s[0]));
    162220                if (s[1] == "Unavailable")
     
    171229                    obj.AllDayEvent = false;
    172230                if (s[5] == "true" && !obj.Recurring)
    173                 {
     231                {//Recurrence set
    174232                    obj.Recurring = true;
    175233                    if (s[6] == "00000000-0000-0000-0000-000000000000")
    176                     {
     234                    {//Creates new recurrence
    177235                        var dayarr = s[9].Split(',');
    178236                        var start = (new DateTime(1970, 1, 1)).AddMilliseconds(double.Parse(s[7]));
    179237                        var end = (new DateTime(1970, 1, 1)).AddMilliseconds(double.Parse(s[8]));
    180                         //loopAddDowns(start, end, dayarr, obj);
     238                        loopAddDowns(start, end, dayarr, obj);
     239                        adminClient.Delete(obj);
     240                        //Delete needed to prevent doubles in the creation of the recurrency
     241                        //Why: event could be on not included day of the week => loop cannot find that.
    181242                    }
    182243                    else
     
    194255            }
    195256            if( last)
    196             {
     257            {//Last element from save all => Notify client
    197258                Clients.Caller.savingAllDone();
    198259            }
    199260            else if (fresh)
    200             {
     261            {//Refresh for graph needed
    201262                Clients.Caller.savingCurrentDone();
    202263            }
    203264        }
     265        /// <summary>
     266        /// Creates downtimes for a new recurrency
     267        /// </summary>
     268        /// <param name="start">Start date</param>
     269        /// <param name="end">End date</param>
     270        /// <param name="dayarr">Boolean day array (sun = 0,...)</param>
     271        /// <param name="obj">Downtime to recur</param>
    204272        private void loopAddDowns(DateTime start, DateTime end, string[] dayarr, Downtime obj)
    205273        {
    206274            var rid = Guid.NewGuid();
    207             for (; start < end;)
     275            while (start < end)
    208276            {
    209277                if (dayarr[(int)(start.DayOfWeek)] == "true")
    210                 {
     278                {//Check for day of the week
     279                    //Set setting for the downtime to add
    211280                    var temp = new Downtime();
    212                     temp.StartDate = start.AddHours(obj.StartDate.Hour - start.Hour).AddMinutes(obj.StartDate.Minute - start.Minute);
    213                     temp.EndDate = start.AddHours(obj.EndDate.Hour - start.Hour).AddMinutes(obj.EndDate.Minute - start.Minute);
    214                     temp.Id = obj.Id;
     281                    temp.StartDate = start.AddHours(obj.StartDate.Hour - start.Hour)
     282                        .AddMinutes(obj.StartDate.Minute - start.Minute);
     283                    temp.EndDate = start.AddHours(obj.EndDate.Hour - start.Hour)
     284                        .AddMinutes(obj.EndDate.Minute - start.Minute);
     285                    temp.Id = Guid.Empty;
    215286                    temp.DowntimeType = obj.DowntimeType;
    216287                    temp.AllDayEvent = obj.AllDayEvent;
  • branches/WebJobManager/HeuristicLab.Clients.Hive.WebJobManager/Hubs/UserInfoHub.cs

    r13741 r13805  
    11using HeuristicLab.Clients.Access.Administration;
     2using HeuristicLab.Clients.Hive.WebJobManager.Controllers;
    23using HeuristicLab.Clients.Hive.WebJobManager.Services;
    34using HeuristicLab.Clients.Hive.WebJobManager.ViewModels.User;
     
    1011namespace HeuristicLab.Clients.Hive.WebJobManager.Hubs
    1112{
     13    /// <summary>
     14    /// Small SignalR hub to change the password from a user
     15    /// </summary>
    1216    public class UserInfoHub: Hub
    1317    {
     
    1519        private Guid userId;
    1620        private AccessAdministrationClient aac;
     21        /// <summary>
     22        /// Loads required services
     23        /// </summary>
    1724        private void loader()
    1825        {
     
    2936            }
    3037        }
    31 
     38        /// <summary>
     39        /// Request to change pass
     40        /// </summary>
     41        /// <param name="user">User id</param>
    3242        public void resetPassword(string user)
    3343        {
     
    3646            Access.User u = new UserViewModel(aac).refreshUsers().getUserById(userid);
    3747            var pass = aac.resetPassword(userid);
     48            UserController.sendPassmail(u, pass);//Send mail + show pass           
    3849            Clients.Caller.showNewPass(pass);
    3950        }
  • branches/WebJobManager/HeuristicLab.Clients.Hive.WebJobManager/Scripts/Hubs/CalendarHubber.js

    r13795 r13805  
    1212               var hubber = $.connection.calendarHub;
    1313
    14                vm.alertMessage = "No alerts";
    15                vm.currentcal = [];
    16                $scope.permission = false;
    17                vm.selectedEventId = -1;
    18                vm.groups = [];
    19                vm.clients = [];
     14               vm.currentcal = [];//Reference to current calendar (treeview.currentNode.calendar)
     15               $scope.permissionview = false;//Show permissions or not
     16               $scope.resaddview = false;//Show add resources or not
     17               vm.selectedEventId = -1;//Selected downtime (-1 for none)
     18               vm.groups = []; //All resource groups
     19               vm.clients = []; //All resources
    2020               vm.init = function () {
    21 
    22                    //  $.connection.hub.logging = true;
    23 
    2421
    2522                   var v = document.getElementById("userId").innerHTML;
    2623                   $.connection.hub.qs = { 'userid': v };
     24                   //Connection string set to identify the unique session ID for the user
    2725                   $.connection.hub.start().done(function () {
    28                        hubber.server.requestInfo();
    29                    });
     26                       hubber.server.requestInfo();//initial data request
     27                   });
     28
     29                   //Process all initial data needed (heavy load)
    3030                   hubber.client.processData = function (data, users, groups) {
    3131                       vm.data = JSON.parse(data);
     
    3636                       $scope.$apply();
    3737                   };
     38
     39                   //Saving from current graph is done -> refresh it
    3840                   hubber.client.savingCurrentDone = function () {
    3941                       vm.calendarSaver = false;
     
    4143                       $scope.$apply();
    4244                   };
     45
     46                   //Saving all graphs done -> clear everything
    4347                   hubber.client.savingAllDone = function () {
    4448                       vm.calendarSaver = false;
     
    4650                       $scope.$apply();
    4751                   };
     52
     53                   //Dispose toggle refresh for current
    4854                   hubber.client.processDispose = function (disp) {
    4955                       vm.treeview.currentNode.IsDisposable = disp;
     
    5157                       $scope.$apply();
    5258                   }
     59
     60                   //Permissions refresh for specific resource
    5361                   hubber.client.processPermissions = function (id, perm) {
    5462                       var json = JSON.parse(perm);
     
    5967                       $scope.$apply();
    6068                   }
     69
     70                   //Process downtimes for a resource. Data conversion
    6171                   hubber.client.processDowntime = function (id, down) {
    6272                       var json = JSON.parse(down);
     
    98108                   }
    99109
     110                   //Initial function to build the resource tree
     111                   $scope.buildTree = function () {
     112                       vm.tree = [];
     113                       vm.temptree = [];
     114                       vm.top = false;
     115                       var ungrouped = {
     116                           children: [],
     117                           Name: 'Ungrouped'
     118                       }
     119                       for (; vm.data.length > 0;) {
     120
     121                           if (vm.data[0].ParentResourceId == null && vm.data[0].IsDisposable !== undefined) {
     122                               var curr = $scope.seekChildren(vm.data.splice(0, 1)[0]);
     123                               vm.clients.push(curr);
     124                               ungrouped.children.push(curr);
     125                           }
     126                           else if (vm.data[0].ParentResourceId == null) {
     127                               var curr = $scope.seekChildren(vm.data.splice(0, 1)[0]);
     128                               vm.groups.push(curr);
     129                               vm.tree.push(curr);
     130                           }
     131                           else {
     132                               var curr = $scope.seekChildren(vm.data.splice(0, 1)[0]);
     133                               if (curr.IsDisposable !== undefined)
     134                                   vm.clients.push(curr);
     135                               else
     136                                   vm.groups.push(curr);
     137                               vm.temptree.push(curr);
     138                           }
     139                       }
     140                       vm.tree.push(ungrouped);
     141
     142                   };//End for hubber init
     143
     144                   //menu navigation
     145                   $scope.menuchange = function (i) {
     146                       switch (i) {
     147                           case 0:
     148                               $scope.permissionview = false;
     149                               $scope.resaddview = false;
     150                               break;
     151                           case 1:
     152                               $scope.permissionview = true;
     153                               $scope.resaddview = false;
     154                               break;
     155                           case 2:
     156                               $scope.permissionview = false;
     157                               $scope.resaddview = true;
     158                               break;
     159                       }
     160                   }
     161
     162                   //Seeks for children, used recursively for building the treeview
     163                   $scope.seekChildren = function (current) {
     164                       current.calendar = [];
     165                       current.children = [];
     166                       current.todelete = [];
     167                       current.changes = false;
     168                       current.collapsed = true;
     169                       for (var t = 0; t < vm.temptree.length;) {
     170                           if (current.Id == vm.temptree[t].ParentResourceId) {
     171                               current.children.push(vm.temptree.splice(t, 1)[0]);
     172                           }
     173                           else {
     174                               t++;
     175                           }
     176                       }
     177                       var childc = current.children.length;//Remembers count of children received from temp tree;
     178                       for (var t = 0; t < vm.data.length;) {
     179                           if (current.Id == vm.data[t].ParentResourceId) {
     180                               if (vm.data[t].IsDisposable !== undefined)
     181                                   vm.clients.push(vm.data[t]);
     182                               else
     183                                   vm.groups.push(vm.data[t]);
     184                               current.children.push(vm.data.splice(t, 1)[0]);
     185                           }
     186                           else {
     187                               t++;
     188                           }
     189                       }
     190                       for (var t = childc; t < current.children.length; t++) {
     191                           current.children[t] = $scope.seekChildren(current.children[t]);
     192                       }
     193                       return current;
     194                   }
     195
     196                   //Change to another resource
    100197                   $scope.$watch("treeview.currentNode", function (newValue, oldValue) {
    101198                       $scope.currentcal = [];
     199                       $scope.resaddview = false;
    102200                       $(".selected.ng-binding").addClass('loaded');
    103201                       $scope.selectedEventId = -1;
    104202                       
     203                       //Check if resource already has downtime data loaded
    105204                       if ($scope.treeview.currentNode != null && $scope.treeview.currentNode.Id != undefined) {
    106205                           if ($scope.treeview.currentNode.calendar.length === 0) {
     206                               //Reach out to server to receive resource data
    107207                               hubber.server.requestPermissions(vm.treeview.currentNode.Id);
    108208                               hubber.server.requestDownTime(vm.treeview.currentNode.Id);
     
    112212                               $timeout(function () {
    113213                                   refreshPermissions();
     214                                   //set previously loaded data
    114215                                   $scope.currentcal = $scope.treeview.currentNode.calendar;
    115216                               }, 0);
    116217
    117218                           }
    118                        }
    119 
    120                    });
    121                }
     219                           $scope.refreshAdds();
     220                       }
     221
     222                   });
     223               }
     224
     225               //Resets the add resources menu
     226               $scope.refreshAdds = function() {
     227                   for (var i = 0; i < $scope.clients.length; i++) {
     228                       $scope.clients[i].add = false;
     229                       for (var j = 0; j < $scope.treeview.currentNode.children.length; j++) {
     230                           if ($scope.clients[i].Id === $scope.treeview.currentNode.children[j].Id)
     231                               $scope.clients[i].add = true;
     232                       }
     233                   }
     234               }
     235
     236               //Resets the permissions menu
    122237               function refreshPermissions() {
    123238                   for (var i = 0; i < $scope.permUsers.length; i++){
     
    136251                   }
    137252               }
     253
     254               //Add resource group show by clearing the tree
    138255               $scope.clearTreeSelect = function () {
    139256                   if (vm.treeview.currentNode != undefined) {
     
    143260                   }
    144261               }
    145                $scope.buildTree = function () {
    146                    vm.tree = [];
    147                    vm.temptree = [];
    148                    vm.top = false;
    149                    var ungrouped = {
    150                        children: [],
    151                        Name: 'Ungrouped'
    152                    }
    153                    for (; vm.data.length > 0;) {
    154 
    155                        if (vm.data[0].ParentResourceId == null && vm.data[0].IsDisposable !== undefined) {
    156                            var curr = $scope.seekChildren(vm.data.splice(0, 1)[0]);
    157                            vm.clients.push(curr);
    158                            ungrouped.children.push(curr);
    159                        }
    160                        else if (vm.data[0].ParentResourceId == null) {
    161                            var curr = $scope.seekChildren(vm.data.splice(0, 1)[0]);
    162                            vm.groups.push(curr);
    163                            vm.tree.push(curr);
    164                        }
    165                        else {
    166                            var curr = $scope.seekChildren(vm.data.splice(0, 1)[0]);
    167                            if (curr.IsDisposable !== undefined)
    168                                vm.clients.push(curr);
    169                            else
    170                                vm.groups.push(curr);
    171                            vm.temptree.push(curr);
    172                        }
    173                    }
    174                    vm.tree.push(ungrouped);
    175 
    176                };
    177 
    178                $scope.seekChildren = function (current) {
    179                    current.calendar = [];
    180                    current.children = [];
    181                    current.todelete = [];
    182                    current.changes = false;
    183                    current.collapsed = true;
    184                    for (var t = 0; t < vm.temptree.length;) {
    185                        if (current.Id == vm.temptree[t].ParentResourceId) {
    186                            current.children.push(vm.temptree.splice(t, 1)[0]);
    187                        }
    188                        else {
    189                            t++;
    190                        }
    191                    }
    192                    var childc = current.children.length;//Remembers count of children received from temp tree;
    193                    for (var t = 0; t < vm.data.length;) {
    194                        if (current.Id == vm.data[t].ParentResourceId) {
    195                            if (vm.data[t].IsDisposable !== undefined)
    196                                vm.clients.push(vm.data[t]);
    197                            else
    198                                vm.groups.push(vm.data[t]);
    199                            current.children.push(vm.data.splice(t, 1)[0]);
    200                        }
    201                        else {
    202                            t++;
    203                        }
    204                    }
    205                    for (var t = childc; t < current.children.length; t++) {
    206                        current.children[t] = $scope.seekChildren(current.children[t]);
    207                    }
    208                    return current;
    209                }
     262
     263               //Reach out to server to toggle disposable for current calendar
    210264               $scope.toggleDisposable = function () {
    211265                   $scope.calendarDispose = true;
    212266                   hubber.server.toggleDisposable(vm.treeview.currentNode.Id);
    213267               }
     268
     269               //Pushes permissions to server
    214270               $scope.pushPermissions = function () {
    215271                   var perms = [];
     
    226282                   hubber.server.changePermissions(perms, node.Id);
    227283               }
     284
     285               //Collects all data from a single resource to save to the server
    228286               function collectInfoToSave(node, refresh, last) {
    229287                   var arr = node.calendar.down[0];
     
    233291                   for (var i = 0; i < arr.length; i++) {
    234292                       if (arr[i].id === '00000000-0000-0000-0000-000000000000') {
     293                           //NEW DOWNTIME
    235294                           var t = arr[i].allDay.toString();
    236295                           toadd.push([
     
    250309                       }
    251310                       else if (arr[i].changed === true) {
     311                           //EDIT EXISTING DOWNTIME
    252312                           var t = arr[i].allDay.toString();
    253313                           toupd.push([
     
    269329                   hubber.server.saveCalendar(node.Id, todel, toadd, toupd, refresh, last);
    270330               }
     331
     332               //Save current calendar
    271333               $scope.saveCurrentCalendar = function () {
    272334                   vm.calendarSaver = true;
    273                    collectInfoToSave(vm.treeview.currentNode, true, false);
     335                   collectInfoToSave(vm.treeview.currentNode, true, false);//true for refresh, false for save all
    274336                   //true for refresh, false for showing it's only one calendar saved.
    275337               }
     338
     339               //Save all changed calendars
    276340               $scope.saveAllCalendars = function () {
    277341
     
    289353                   }).then(function (success) {
    290354                       vm.calendarSaver = true;
     355
    291356                       for (var i = 0; i < $scope.allSave.length; i++) {
    292357                           if (i >= $scope.allSave.length - 1)
     
    299364
    300365               }
     366
     367               //Checks treeview for edits and builds new array containing these (recurse for children)
    301368               function createSaveRequests(node) {
    302369                   if (node.changes === true)
     
    306373                   }
    307374               }
     375
     376               //Clears and refreshes calendar for current resource (delete current changes)
    308377               $scope.clearCurrentCalendar = function () {
    309378
     
    319388
    320389               }
     390
     391               //Clears all calendars and refreshes current (Deletes all changes)
    321392               $scope.clearAllCalendars = function () {
    322393                   ngDialog.openConfirm({
     
    333404
    334405               }
     406
     407               //Function that clears all calendar (separate so dialog is not called when saveAll is finished)
    335408               function clearAllCalendarsFunc() {
    336409                   $(".ng-binding.changed").removeClass('changed');
     
    347420                   $(".selected.ng-scope").addClass('loaded');
    348421               }
     422
     423               //Recurse trough tree view
    349424               function clearCalendarsRecurse(node) {
    350425
     
    356431                   }
    357432               }
     433
     434               //Delete all downtimes from current resource
    358435               $scope.deleteAllEvents = function () {
    359436                   vm.calendarDeleter = true;
     
    373450                   });
    374451               }
     452
     453               //Delete all past events
    375454               $scope.deleteAllPreviousEvents = function () {
    376455                   vm.calendarDeleter = true;
     
    395474               }
    396475
    397 
     476               //Sets the status of a downtime AND the current resource to changed
    398477               $scope.setChanged = function (id) {
    399478                   if (id != -1) {
     
    408487                   $(".selected").addClass('changed');
    409488               }
    410                //*Add event by click
     489
     490               //Adds event by click on empty space
    411491               $scope.calendarClick = function (date, jsEvent, view) {
    412492
     
    418498                   end.setHours(dat.getHours() + 2);
    419499                   vm.treeview.currentNode.calendar.down[0].push({
    420                        id: '00000000-0000-0000-0000-000000000000',
     500                       id: '00000000-0000-0000-0000-000000000000',//Makes it recognizable as new for the server
    421501                       title: 'Unavailable',
    422502                       start: dat,
     
    440520
    441521               }
     522
     523               //Finds array index for specific _id
    442524               function checkId(id) {
    443525                   for (var i = 0; i < vm.treeview.currentNode.calendar.down[0].length ; i++) {
     
    447529                   return -1;
    448530               }
    449                /* alert on eventClick */
     531               //Set selected downtime
    450532               $scope.eventClick = function (date, jsEvent, view) {
    451533                   vm.selectedEventId = checkId(date._id);
    452534               };
     535               //Sets selected downtime by clicking on the button at bottom on the page, moves to date
    453536               $scope.eventClickBtn = function (id) {
    454537                   vm.selectedEventId = checkId(id);
    455538                   vm.goToDate();
    456539               };
    457                /* alert on Drop */
     540
     541               //Drag and drop downtime
    458542               $scope.dragandDrop = function (event, delta, revertFunc, jsEvent, ui, view) {
    459543                   vm.selectedEventId = checkId(event._id);
     
    474558                   vm.treeview.currentNode.calendar.down[0][vm.selectedEventId].end = new Date(event.end);
    475559               };
    476                /* alert on Resize */
     560               //Resize downtime
    477561               $scope.resizeEvent = function (event, delta, revertFunc, jsEvent, ui, view) {
    478562                   vm.selectedEventId = checkId(event._id);
     
    482566               };
    483567
    484                /* remove event */
     568               //Removes a downtime from client (existing downtime gets referenced in todelete
    485569               $scope.remove = function (index) {
    486570                   vm.selectedEventId = -1;
     
    493577
    494578               };
     579               //Remove trough list view at bottom
    495580               $scope.removeList = function (id) {
    496581                   var index = checkId(id);
     
    504589
    505590               };
    506 
     591               //Check if start is before end AND start is after now (recursion)
    507592               $scope.checkDateStartEnd = function () {
    508593                   if ($scope.currentcal.down[0][vm.selectedEventId].rec.start > $scope.currentcal.down[0][vm.selectedEventId].rec.end ||
     
    515600                       $scope.currentcal.down[0][vm.selectedEventId].rec.start = new Date();
    516601               }
    517                //pushes all changes to other recurs
     602               //pushes all changes to other existing recurs and creates new downtimes where needed
    518603               $scope.pushRecurChanges = function (recid) {
    519604                   ngDialog.openConfirm({
     
    526611                       plain: true
    527612                   }).then(function (success) {
     613
    528614                       var arr = vm.treeview.currentNode.calendar.down[0];
     615                       //Deep copy of downtime for referencing
    529616                       var ob = $.extend(true, {}, arr[vm.selectedEventId]);
    530                        for (var i = 0; i < arr.length;) {
     617
     618                       for (var i = 0; i < arr.length;) {//Go trough downtimes and find all recurrences
    531619                           if (arr[i].rec.recid === recid) {
    532620                               if (new Date(arr[i].start) < new Date(ob.rec.start) ||
    533621                                        new Date(arr[i].end) > new Date(ob.rec.end) ||
    534622                                        !ob.rec.days[new Date(arr[i].start).getDay()]) {
    535                                    vm.remove(i);
     623                                   //Downtime is out of recurrence boundaries
     624                                   //Before start date OR After end date OR Not on right day of the week
     625                                   vm.remove(i);//NO I++ -> REMOVE SPLICES ARRAY
    536626                                   vm.selectedEventId = -1;
    537627
    538628                               }
    539629                               else {
    540 
     630                                   //Edit downtime when it is within the bounds
    541631                                   arr[i].start.setHours(ob.start.getHours(), ob.start.getMinutes());
    542632                                   arr[i].end.setHours(ob.end.getHours(), ob.end.getMinutes());
     
    551641                               i++;
    552642                       }
     643                       //init for new downtimes.
    553644                       var start = new Date(ob.rec.start);
    554                        start.setHours(2, 0, 0, 0);
     645                       start.setHours(2, 0, 0, 0);//Beginning of the day + time conversion +02
    555646                       var end = new Date(ob.rec.end);
    556                        end = new Date(end.setHours(24, 0, 0, 0) + 1000 * 3600 * 2);
    557 
    558                        loop1:
     647                       end = new Date(end.setHours(24, 0, 0, 0) + 1000 * 3600 * 2);//End of the day + time conversion +02
     648
     649                       loop1: //Loop start to end with single day increment
    559650                           for (var d = (start.getTime()) ; d < (end.getTime()) ;) {
    560651                               var tog = ob.rec.days[new Date(d).getDay()];
     652                               //Check if day of the week is included in recursion
    561653                               if (tog) {
    562                                    loop2:
     654                                   loop2://Loop checking existing downtime array to see if day is already filled or not
    563655                                       for (var i = 0; i < arr.length; i++) {
    564656
     
    567659                                               if (arr[i].start.getTime() >= d &&
    568660                                                   arr[i].end.getTime() <= dend) {
    569                                                    d += (1000 * 3600 * 24);
    570                                                    continue loop1;
     661                                                   d += (1000 * 3600 * 24);//add day to loop 1
     662                                                   continue loop1;//breaks out of loop2 and skips to next day
    571663                                               }
    572664                                           }
    573665                                       }
    574 
     666                                   //Made it here = new event needed: init
    575667                                   var ts = new Date(d);
    576668                                   ts.setHours(new Date(ob.start).getHours(), new Date(ob.start).getMinutes());
     
    589681                               }
    590682
    591                                d += (1000 * 3600 * 24);// 1 day
    592 
    593                            }
    594                    });
    595                }
     683                               d += (1000 * 3600 * 24);// adds one day
     684
     685                           }
     686                   });
     687               }
     688
     689               //Delete all bound recurrences
    596690               $scope.deleteAllRecurrences = function (recid) {
    597691                   ngDialog.openConfirm({
     
    614708               }
    615709
     710               //Moves calendar to selected date
    616711               $scope.goToDate = function () {
    617712                   $("#resourcecalendar").fullCalendar('gotoDate', vm.currentcal.down[0][vm.selectedEventId].start);
    618713               }
    619                /* Render Tooltip */
     714               /* Renders Tooltip */
    620715               $scope.eventRender = function (event, element, view) {
    621716                   element.attr({
     
    625720                   //$compile(element)($scope);
    626721               };
    627                /* config object */
     722               //Calendar configuration
    628723               $scope.uiConfig = {
    629724                   calendar: {
     
    650745               };
    651746
     747               
     748
    652749
    653750
    654751           }).filter('disp', function () {
    655                return function (input) {
     752               return function (input) {//Filter boolean to string
    656753                   return input ? 'Disposable' : 'Not disposable';
    657754               }
    658755           }).directive('animateOnChange', function ($timeout) {
    659                return function (scope, element, attr) {
     756               return function (scope, element, attr) {//Animation on downtime info to show change
    660757                   scope.$watch(attr.animateOnChange, function (nv, ov) {
    661758
     
    665762                               $timeout(function () {
    666763                                   element.removeClass('changed');
    667                                }, 250); // Could be enhanced to take duration as a parameter
     764                               }, 250);
    668765                           }
    669766                           else {
     
    671768                               $timeout(function () {
    672769                                   element.removeClass('changedshut');
    673                                }, 250); // Could be enhanced to take duration as a parameter
     770                               }, 250);
    674771                           }
    675772                       }
  • branches/WebJobManager/HeuristicLab.Clients.Hive.WebJobManager/Scripts/Hubs/UserInfoHubber.js

    r13754 r13805  
    22
    33$(function () {
    4     $.connection.hub.logging = true;
     4    //$.connection.hub.logging = true;
    55    var v = document.getElementById("userId").innerHTML;
    66    console.log(v);
     
    88    $.connection.hub.start();
    99    hubber.client.showNewPass = function (pass) {
    10         $("#inppassreset").html("<label class=' control-label' style='text-align:left'>New password: " + pass + "</label>");
     10        $("#inppassreset").html("<label class=' control-label' style='text-align:left'>New pass: " + pass + ". An email has been sent to the user containing the new password</label>");
    1111                                     
    1212    };
  • branches/WebJobManager/HeuristicLab.Clients.Hive.WebJobManager/Scripts/Styling/angular.treeview.css

    r13795 r13805  
    6161
    6262    div[data-tree-model] li.selected {
    63         box-shadow:  2px 3px 5px rgba(0,0,0,0.6), inset 1px 10px 300px 51px rgba(143,201,58,1)!important;
     63        box-shadow:  2px 3px 5px rgba(0,0,0,0.6), inset 1px 10px 300px 51px #5cb85c!important;
    6464    }
    6565    div[data-tree-model] span.selected {
  • branches/WebJobManager/HeuristicLab.Clients.Hive.WebJobManager/Services/Imports/AccessAdministrationClient.cs

    r13754 r13805  
    3131namespace HeuristicLab.Clients.Access.Administration
    3232{
     33    /// <summary>
     34    /// Controls everything User/Group/Role related
     35    /// </summary>
    3336    [Item("AccessAdministrationClient", "AccessAdministration client.")]
    3437    public class AccessAdministrationClient : IContent
  • branches/WebJobManager/HeuristicLab.Clients.Hive.WebJobManager/Services/WebLoginService.cs

    r13754 r13805  
    124124        }
    125125
     126        /// <summary>
     127        /// Returns the AccessAdministrationClient used for User/Group/Role management
     128        /// </summary>
     129        /// <param name="id"></param>
     130        /// <returns></returns>
    126131        public AccessAdministrationClient getAccessAdminClient(Guid id)
    127132        {
    128133            return accessclients.Find(x => x.userId == id);
    129134        }
     135        /// <summary>
     136        /// Returns HiveAdminClient used for Resource management
     137        /// </summary>
     138        /// <param name="id"></param>
     139        /// <returns></returns>
    130140        public HiveAdminClientWeb getAdminClient(Guid id)
    131141        {
  • branches/WebJobManager/HeuristicLab.Clients.Hive.WebJobManager/ViewModels/User/UserViewModel.cs

    r13754 r13805  
    77namespace HeuristicLab.Clients.Hive.WebJobManager.ViewModels.User
    88{
     9    /// <summary>
     10    /// ViewModel containing User/Group/Role data
     11    /// </summary>
    912    public class UserViewModel
    1013    {
     
    2427        public List<Access.UserGroupBase> SelectedRoleEnrolled { get; set; }
    2528
     29        /// <summary>
     30        /// Initialize viewmodel and set up connection
     31        /// </summary>
     32        /// <param name="ac">AccessAdminClient for connection</param>
    2633        public UserViewModel(AccessAdministrationClient ac)
    2734        {
     
    4047           
    4148        }
     49        /// <summary>
     50        /// Refreshes Users, Groups and Roles
     51        /// </summary>
     52        /// <returns></returns>
    4253        public UserViewModel refreshAll()
    4354        {
     
    4758            return this;
    4859        }
     60        /// <summary>
     61        /// Refreshes only the Users
     62        /// </summary>
     63        /// <returns></returns>
    4964        public UserViewModel refreshUsers()
    5065        {
     
    5368            return this;
    5469        }
     70        /// <summary>
     71        /// Refreshes only the Roles
     72        /// </summary>
     73        /// <returns></returns>
    5574        public UserViewModel refreshRoles()
    5675        {
     
    5978            return this;
    6079        }
     80        /// <summary>
     81        /// Refreshes only the User Groups
     82        /// </summary>
     83        /// <returns></returns>
    6184        public UserViewModel refreshGroups()
    6285        {
     
    6588            return this;
    6689        }
     90        /// <summary>
     91        /// Returns a user by its Id
     92        /// </summary>
     93        /// <param name="id">User Id</param>
     94        /// <returns></returns>
    6795        public Access.User getUserById(Guid id)
    6896        {
    6997            return users.Find(x => x.Id == id);
    7098        }
     99        /// <summary>
     100        /// Returns a group by its Id
     101        /// </summary>
     102        /// <param name="id">Group id</param>
     103        /// <returns></returns>
    71104        public Access.UserGroup getGroupById(Guid id)
    72105        {
    73106            return ugroups.Find(x => x.Id == id);
    74107        }
     108        /// <summary>
     109        /// Returns a role by its name
     110        /// </summary>
     111        /// <param name="name">Role name</param>
     112        /// <returns></returns>
    75113        public Access.Role getRoleByName(string name)
    76114        {
  • branches/WebJobManager/HeuristicLab.Clients.Hive.WebJobManager/Views/Resource/Index.cshtml

    r13795 r13805  
    88
    99    <div class="col-sm-4">
    10         <div class="btn-group btn-group-justified" style="padding:3px;margin-bottom:-10px"
     10        <div class="btn-group btn-group-justified" style="padding:3px;margin-bottom:-12px"
    1111             role="group">
    1212            <a class="btn btn-info btn-lg btn-block disabled"
     
    4848            </h3>
    4949            <ul class="nav nav-pills nav-justified">
    50                 <li role="presentation" ng-class="{ 'active': !permission }" ng-style="{ 'text-decoration': !permission ? 'underline' : ''}">
     50                <li role="presentation"
     51                    ng-class="{ 'active': !permissionview && !resaddview }"
     52                    ng-style="{ 'text-decoration': !permissionview && !resaddview ? 'underline' : ''}">
    5153                    <a style="text-shadow:2px 2px black; color:white; font-weight:bold; border: 1px solid white;"
    5254                       href=""
    53                        ng-click="permission = false">
     55                       ng-click="menuchange(0)">
    5456                        Resource info
    5557                    </a>
    5658                </li>
    57                 <li role="presentation" ng-class="{ 'active': permission }" ng-style="{ 'text-decoration': permission ? 'underline' : ''}">
     59                <li role="presentation"
     60                    ng-class="{ 'active': permissionview }"
     61                    ng-style="{ 'text-decoration': permissionview ? 'underline' : ''}">
    5862                    <a style="text-shadow:2px 2px black; color:white; font-weight:bold; border: 1px solid white;"
    5963                       href=""
    60                        ng-click="permission = true">
     64                       ng-click="menuchange(1)">
    6165                        Permissions
    6266                    </a>
    6367                </li>
     68                <li ng-if="treeview.currentNode.IsDisposable === undefined"
     69                    role="presentation"
     70                    ng-class="{ 'active': resaddview }"
     71                    ng-style="{ 'text-decoration': resaddview ? 'underline' : ''}">
     72
     73                    <a style="text-shadow:2px 2px black; color:white; font-weight:bold; border: 1px solid white;"
     74                       href=""
     75                       ng-click="menuchange(2)">
     76                        Add resources
     77                    </a>
     78                </li>
    6479            </ul>
    65            
    66             <form ng-show="permission"
     80            <form ng-show="!permissionview && resaddview"
    6781                  method="post"
    68                   asp-action="editPermissions"
     82                  asp-action="addResourcesToGroup"
    6983                  asp-controller="Resource"
    7084                  enctype="multipart/form-data"
    71                   class="row panel-heading"
    72                   >
    73                 <div
    74                      class="row" style="padding:10px;">
     85                  class="row panel-heading">
     86                <div class="row" style="padding:5px;">
     87                    <h4>Info</h4>
     88                    <p>
     89                        This shows only
     90                        <span style="text-decoration:underline">direct members</span>
     91                        of the group (not members of subgroups).
     92                    </p>
     93                    <p>Adding a member will overwrite the current group it's a member in (if any)</p>
     94                    <p>Removing an existing member will make it revert to Ungrouped.</p>
     95                    <a ng-click="refreshAdds()" href=""
     96                       class="btn btn-info pull-right"
     97                       style="box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);
     98                            text-shadow:2px 2px black;">Reset to current members</a>
     99                    <div class="row" style="margin:5px">
     100                        <h4>All resources</h4>
     101                        <label class="col-sm-3"
     102                               ng-style="{
     103                                   'background-color':client.add === true ? 'green' : '' }"
     104                               ng-repeat="client in clients  | orderBy:['!add', 'Name' ]  | filter:searchText">
     105                            <input type="checkbox"
     106                                   name="addres"
     107                                   value="{{client.Id}}"
     108                                   ng-model="client.add"> {{client.Name}}
     109                        </label>
     110                    </div>
     111                </div>
     112                <input style="display:none"
     113                       type="text"
     114                       id="groupid"
     115                       name="groupid"
     116                       value="{{treeview.currentNode.Id}}" />
     117
     118                <button type="submit"
     119                        id="inpsaver"
     120                        class="btn btn-success pull-right"
     121                        style="box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);
     122                            text-shadow:2px 2px black;">
     123                    <i class="fa fa-save"></i>
     124                    Add resources to group
     125                </button>
     126            </form>
     127            <form ng-show="permissionview && !resaddview"
     128                  method="post"
     129                  enctype="multipart/form-data"
     130                  class="row panel-heading">
     131                <div class="row" style="padding:10px;">
    75132                    <h4>Groups</h4>
    76133                    <label class="col-sm-3" ng-repeat="group in permGroups">
    77                         <input type="checkbox" 
    78                                name="permgroups" 
     134                        <input type="checkbox"
     135                               name="permgroups"
    79136                               value="{{group.Id}}"
    80137                               ng-model="group.state"> {{group.Name}}
     
    84141                    <h4>Users</h4>
    85142                    <label class="col-sm-3 col-lg-2" ng-repeat="user in permUsers">
    86                         <input type="checkbox" 
    87                                name="permusers" 
     143                        <input type="checkbox"
     144                               name="permusers"
    88145                               value="{{user.Id}}"
    89146                               ng-model="user.state"> {{user.UserName}}
    90147                    </label>
    91148                </div>
    92                 <div class="btn btn-info pull-right"
     149                <div class="btn btn-success pull-right"
    93150                     style="box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);
    94151                            text-shadow:2px 2px black;"
    95152                     ng-click="pushPermissions()">
    96                 <i ng-if="permissionLoader" class="fa fa-spin fa-save"></i>
    97                 Save permission changes</div>
     153                    <i ng-if="permissionLoader" class="fa fa-spin fa-save"></i>
     154                    Save permission changes
     155                </div>
    98156            </form>
    99             <form ng-show="!permission"
     157            <form ng-show="!permissionview && !resaddview"
    100158                  method="post"
    101159                  asp-action="deleteClientGroup"
     
    155213                        <tr>
    156214                            <td>Memory (free/total)</td>
    157                             <td>{{treeview.currentNode.FreeMemory/1024 | number:1}} GB / {{treeview.currentNode.Memory/1024 | number:1}} GB</td>
     215                            <td>{{treeview.currentNode.FreeMemory/1024 | number:1}} / {{treeview.currentNode.Memory/1024 | number:1}} GB</td>
    158216                        </tr>
    159217
     
    161219                </table>
    162220            </form>
    163             <form method="post"
     221            <form method="post" ng-show="!permissionview && !resaddview"
    164222                  asp-action="changeParent"
    165223                  asp-controller="Resource"
     
    169227                <input style="display:none" type="text" id="inpid" name="inpid" value="{{treeview.currentNode.Id}}" />
    170228
    171                 <span style="padding:0px" class="col-sm-4">Change parent resource: </span>
     229                <span style="padding:0px" class="col-sm-4">Change group: </span>
    172230
    173231                <select class="form-control col-sm-5"
     
    190248                            text-shadow:2px 2px black;">
    191249                    <i class="fa fa-save"></i>
    192                     Change parent
     250                    Change group
    193251                </button>
    194252            </form>
     
    485543                <h3>Choose resources </h3>
    486544                <h5>(This will overwrite the group set for these resources)</h5>
    487                 <table>
    488                     <tr ng-repeat="client in clients  | orderBy:['Name'] track by $index" class="checkbox col-md-6 col-lg-4">
    489                         <td>
    490                             <label>
    491                                 <input type="checkbox"
    492                                        name="clientstoadd"
    493                                        value="{{client.Id}}">
    494                                 <i class="fa fa-desktop" aria-hidden="true"></i> {{client.Name | limitTo : 7}} - {{client.Cores}}x {{client.CpuSpeed/1000 |  number:1}} GHz - {{client.Memory / 1024 | number:1}} GB
    495                             </label>
    496                         </td>
    497                     </tr>
    498                 </table>
     545                <label>Search: <input ng-init="searchText = ''" ng-model="searchText"></label>
     546                <div class="row">
     547                    <div style="margin:0px"
     548                         ng-repeat="client in clients  | orderBy:['Name']  | filter:searchText" class="checkbox col-md-6 col-lg-4">
     549
     550                        <label ng-style="{
     551                                   'background-color':client.checked === true ? 'green' : '',
     552                                    'color':client.checked === true ? 'white' : ''  }"
     553                               style="border-radius:5px">
     554                            <input type="checkbox"
     555                                   name="clientstoadd"
     556                                   ng-model="client.checked"
     557                                   value="{{client.Id}}" />
     558                            <i class="fa fa-desktop" aria-hidden="true"></i> {{client.Name | limitTo : 7}} - {{client.Cores}}x {{client.CpuSpeed/1000 |  number:1}} GHz - {{client.Memory / 1024 | number:1}} GB
     559                        </label>
     560
     561                    </div>
     562                </div>
    499563            </div>
    500564        </form>
  • branches/WebJobManager/HeuristicLab.Clients.Hive.WebJobManager/Views/User/Groups.cshtml

    r13754 r13805  
    3737         style="padding:10px; margin-right:0px!important">
    3838        <div class="col-sm-4">
    39             <div class="btn-group-vertical btn-block">
     39            <div class="btn-group btn-group-justified btn-block"
     40                 role="group" style="margin-bottom:-4px">
     41
    4042                <a class="btn btn-info btn-lg btn-block disabled"
    41                    style="box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);
     43                   style="width:6%;box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);
    4244                            text-shadow:2px 2px black;">
    4345                    <i class="fa fa-group"></i> @Model.ugroups.Count Group@(Model.ugroups.Count != 1 ? "s" : "")
     
    5254                   style="box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);
    5355                            text-shadow:2px 2px black;">
    54                     <i class="fa fa-plus-circle"></i> Add new group
     56                    <i class="fa fa-plus-circle"></i>
    5557                </a>
     58            </div>
     59            <div class="btn-group-vertical btn-block">
     60               
    5661                @foreach (var group in Model.ugroups)
    5762                {
     
    128133                                </div>
    129134                            </div>
    130 
     135                            <input type="text"
     136                                   style="display:none"
     137                                   id="u"
     138                                   name="u"
     139                                   value="@Model.SelectedGroup.Id" />
    131140
    132141                            @if (Model.SelectedGroup.Id != Guid.Empty)
  • branches/WebJobManager/HeuristicLab.Clients.Hive.WebJobManager/Views/User/Index.cshtml

    r13754 r13805  
    4747        {
    4848            <div class="col-sm-4">
    49                 <div class="btn-group-vertical btn-block">
    50                     <a class="btn btn-info btn-lg btn-block disabled"
    51                        style="box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);
     49                <div class="btn-group btn-group-justified btn-block"
     50                     role="group" style="margin-bottom:-4px">
     51
     52                    <a class="btn btn-info btn-lg disabled"
     53                       style="width:6%;box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);
    5254                            text-shadow:2px 2px black;">
    5355                        <i class="fa fa-user"></i> @Model.users.Count User@(Model.users.Count != 1 ? "s" : "")
    5456                    </a>
    55                     <a class="btn btn-success btn-block
     57                    <a class="btn btn-success
    5658                       @(Model.SelectedUser.Id == Guid.Empty ? "active" : "")
    5759                       "
     60                       style="box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);
     61                            text-shadow:2px 2px black;"
    5862                       asp-controller="User"
    5963                       asp-action="SelectUser"
    6064                       asp-route-id="@Guid.Empty"
    61                        onclick="showUser()"
    62                        style="box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);
    63                             text-shadow:2px 2px black;">
    64                         <i class="fa fa-user-plus"></i> Add new user
     65                       onclick="showUser()">
     66                        <i class="fa fa-user-plus"></i>
    6567                    </a>
     68                </div>
     69                <div class="btn-group-vertical btn-block">
     70                   
     71                   
    6672                    @foreach (var user in Model.users)
    6773                    {
     
    119125                              method="post"
    120126                              asp-action="saveUser"
    121                               asp-controller="User" 
     127                              asp-controller="User"
    122128                              enctype="multipart/form-data"
    123129                              onsubmit="showSaver()">
     
    181187                                        @Model.SelectedUser.Id
    182188                                    </label>
    183                                    
     189
    184190                                </div>
    185191                                <div class="form-group">
     
    295301                                            {
    296302                                                <div class="row">
    297                                                    
     303
    298304                                                    <p class="col-sm-10"><i class="fa fa-gavel"></i> @r.Name</p>
    299305                                                    <p class="col-sm-2">
     
    359365                                            id="inpsaver"
    360366                                            disabled
    361                                             class="btn btn-default"
    362                                             >
     367                                            class="btn btn-default">
    363368                                        <i class="fa fa-save"></i>
    364369                                        @(Model.SelectedUser.Id != Guid.Empty ? "Save changes" : "Add user")
  • branches/WebJobManager/HeuristicLab.Clients.Hive.WebJobManager/Views/User/Roles.cshtml

    r13754 r13805  
    3838
    3939        <div class="col-sm-4">
    40             <div class="btn-group-vertical btn-block">
     40            <div class="btn-group btn-group-justified btn-block"
     41                 role="group" style="margin-bottom:-4px">
     42
    4143                <a class="btn btn-info btn-lg btn-block disabled"
    42                    style="box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);
     44                   style="width:6%;box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);
    4345                            text-shadow:2px 2px black;">
    4446                    <i class="fa fa-gavel"></i> @Model.roles.Count Role@(Model.roles.Count != 1 ? "s" : "")
     
    5355                   style="box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);
    5456                            text-shadow:2px 2px black;">
    55                     <i class="fa fa-plus-circle"></i> Add new role
     57                    <i class="fa fa-plus-circle"></i>
    5658                </a>
     59            </div>
     60            <div class="btn-group-vertical btn-block">
     61               
    5762                @foreach (var role in Model.roles)
    5863                {
  • branches/WebJobManager/HeuristicLab.Clients.Hive.WebJobManager/wwwroot/css/site.min.css

    r13795 r13805  
    1 @import url(http://fonts.googleapis.com/css?family=Roboto:400);.wrapper,h4{text-align:center}.label,sub,sup{vertical-align:baseline}[role=button],div[data-tree-model] li,div[data-tree-model] li i{cursor:pointer}.fc table,table{border-spacing:0}body,figure{margin:0}.btn-group>.btn-group,.btn-toolbar .btn,.btn-toolbar .btn-group,.btn-toolbar .input-group,.col-xs-1,.col-xs-10,.col-xs-11,.col-xs-12,.col-xs-2,.col-xs-3,.col-xs-4,.col-xs-5,.col-xs-6,.col-xs-7,.col-xs-8,.col-xs-9,.dropdown-menu{float:left}.navbar-fixed-bottom .navbar-collapse,.navbar-fixed-top .navbar-collapse,.pre-scrollable{max-height:340px}.fa,.glyphicon{-moz-osx-font-smoothing:grayscale}body{-webkit-font-smoothing:antialiased;font:400 14px Roboto,arial,sans-serif}.container{padding:25px;position:fixed}.form-login{background-color:#EDEDED;border-radius:15px;border-color:#d2d2d2;border-width:5px;box-shadow:0 1px 0 #cfcfcf;padding:10px 20px 20px;padding:10px 20px 20px}h4{border:0 solid #fff;border-bottom-width:1px;padding-bottom:10px}.panel-warning>.panel-heading{background-image:linear-gradient(to bottom,#eb9114 0,#f1b25b 100%)!important;color:#fff!important}.panel-danger>.panel-heading{background-image:linear-gradient(to bottom,#c12e2a 0,#d9534f 100%)!important;color:#fff!important}.label-as-badge{border-radius:1em}.bar-off{fill:#c2c2d6}.bar-off:hover{fill:#e0e0eb}.bar-wait{fill:#f0a742}.bar-wait:hover{fill:#f4bd71}.bar-trans{fill:#80d4ff}.bar-trans:hover{fill:#9df}.bar-calc{fill:#2f6fa6}.bar-calc:hover{fill:#3884c7}.bar-paus{fill:#47476b}.bar-paus:hover{fill:#5c5c8a}.bar-fin{fill:#5cb85c}.bar-fin:hover{fill:#71c171}.bar-abo{fill:#c2302c}.bar-abo:hover{fill:#d54944}.bar-fail{fill:#c2302c}.bar-fail:hover{fill:#d54944}rect.selection{stroke:gray;stroke-dasharray:4px;stroke-opacity:.5;fill:transparent}svg ::selection{background:0 0}svg ::-moz-selection{background:0 0}svg ::-webkit-selection{background:0 0}.btn-danger:focus,.btn-danger:hover,.btn-default:focus,.btn-default:hover,.btn-info:focus,.btn-info:hover,.btn-primary:focus,.btn-primary:hover,.btn-success:focus,.btn-success:hover,.btn-warning:focus,.btn-warning:hover{background-position:0 -15px}[animate-on-change]{transition:all 1s;-webkit-transition:all 1s}[animate-on-change].changed{background-color:#add8e6;transition:none;-webkit-transition:none}[animate-on-change].changedshut{background-color:#ffa07a;transition:none;-webkit-transition:none}.panel-heading .nav-justified.nav-pills li.active>a{background-color:#74a9d8!important}div[data-angular-treeview]{-moz-user-select:-moz-none;-khtml-user-select:none;-webkit-user-select:none;-ms-user-select:none;user-select:none;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;font-weight:600;color:#fff;text-decoration:none;text-shadow:1px 1px #000}div[data-tree-model] ul{padding:5px;list-style:none;border:#778899;overflow:hidden}div[data-tree-model] li{position:relative;padding:0 0 0 20px;line-height:20px;margin-top:3px;border:#add8e6;border-radius:10px;box-shadow:2px 3px 5px rgba(0,0,0,.6),inset 1px 10px 300px 51px rgba(33,151,184,1)}div[data-tree-model] li .expanded{padding:1px 10px;background-image:url(../img/folder.png);background-repeat:no-repeat}div[data-tree-model] li .collapsed{padding:1px 10px;background-image:url(../img/folder-closed.png);background-repeat:no-repeat}div[data-tree-model] li .normal{padding:1px 10px;color:#000;background-image:url(../img/file.png);background-repeat:no-repeat}div[data-tree-model] li.selected{box-shadow:2px 3px 5px rgba(0,0,0,.6),inset 1px 10px 300px 51px rgba(143,201,58,1)!important}div[data-tree-model] span.selected{color:#fff!important;text-shadow:1px 1px #000!important;font-weight:700;padding:1px 5px}div[data-tree-model] li.changed{box-shadow:2px 3px 5px rgba(0,0,0,.6),inset 1px 10px 300px 51px rgba(250,250,210,1)}div[data-tree-model] span.changed{color:#000;text-shadow:1px 1px #fff;font-weight:700;padding:1px 5px}div[data-tree-model] span.loaded{text-decoration:underline;font-style:oblique}/*!
     1@import url(http://fonts.googleapis.com/css?family=Roboto:400);.wrapper,h4{text-align:center}.label,sub,sup{vertical-align:baseline}[role=button],div[data-tree-model] li,div[data-tree-model] li i{cursor:pointer}.fc table,table{border-spacing:0}body,figure{margin:0}.btn-group>.btn-group,.btn-toolbar .btn,.btn-toolbar .btn-group,.btn-toolbar .input-group,.col-xs-1,.col-xs-10,.col-xs-11,.col-xs-12,.col-xs-2,.col-xs-3,.col-xs-4,.col-xs-5,.col-xs-6,.col-xs-7,.col-xs-8,.col-xs-9,.dropdown-menu{float:left}.navbar-fixed-bottom .navbar-collapse,.navbar-fixed-top .navbar-collapse,.pre-scrollable{max-height:340px}.fa,.glyphicon{-moz-osx-font-smoothing:grayscale}body{-webkit-font-smoothing:antialiased;font:400 14px Roboto,arial,sans-serif}.container{padding:25px;position:fixed}.form-login{background-color:#EDEDED;border-radius:15px;border-color:#d2d2d2;border-width:5px;box-shadow:0 1px 0 #cfcfcf;padding:10px 20px 20px;padding:10px 20px 20px}h4{border:0 solid #fff;border-bottom-width:1px;padding-bottom:10px}.panel-warning>.panel-heading{background-image:linear-gradient(to bottom,#eb9114 0,#f1b25b 100%)!important;color:#fff!important}.panel-danger>.panel-heading{background-image:linear-gradient(to bottom,#c12e2a 0,#d9534f 100%)!important;color:#fff!important}.label-as-badge{border-radius:1em}.bar-off{fill:#c2c2d6}.bar-off:hover{fill:#e0e0eb}.bar-wait{fill:#f0a742}.bar-wait:hover{fill:#f4bd71}.bar-trans{fill:#80d4ff}.bar-trans:hover{fill:#9df}.bar-calc{fill:#2f6fa6}.bar-calc:hover{fill:#3884c7}.bar-paus{fill:#47476b}.bar-paus:hover{fill:#5c5c8a}.bar-fin{fill:#5cb85c}.bar-fin:hover{fill:#71c171}.bar-abo{fill:#c2302c}.bar-abo:hover{fill:#d54944}.bar-fail{fill:#c2302c}.bar-fail:hover{fill:#d54944}rect.selection{stroke:gray;stroke-dasharray:4px;stroke-opacity:.5;fill:transparent}svg ::selection{background:0 0}svg ::-moz-selection{background:0 0}svg ::-webkit-selection{background:0 0}.btn-danger:focus,.btn-danger:hover,.btn-default:focus,.btn-default:hover,.btn-info:focus,.btn-info:hover,.btn-primary:focus,.btn-primary:hover,.btn-success:focus,.btn-success:hover,.btn-warning:focus,.btn-warning:hover{background-position:0 -15px}[animate-on-change]{transition:all 1s;-webkit-transition:all 1s}[animate-on-change].changed{background-color:#add8e6;transition:none;-webkit-transition:none}[animate-on-change].changedshut{background-color:#ffa07a;transition:none;-webkit-transition:none}.panel-heading .nav-justified.nav-pills li.active>a{background-color:#74a9d8!important}div[data-angular-treeview]{-moz-user-select:-moz-none;-khtml-user-select:none;-webkit-user-select:none;-ms-user-select:none;user-select:none;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;font-weight:600;color:#fff;text-decoration:none;text-shadow:1px 1px #000}div[data-tree-model] ul{padding:5px;list-style:none;border:#778899;overflow:hidden}div[data-tree-model] li{position:relative;padding:0 0 0 20px;line-height:20px;margin-top:3px;border:#add8e6;border-radius:10px;box-shadow:2px 3px 5px rgba(0,0,0,.6),inset 1px 10px 300px 51px rgba(33,151,184,1)}div[data-tree-model] li .expanded{padding:1px 10px;background-image:url(../img/folder.png);background-repeat:no-repeat}div[data-tree-model] li .collapsed{padding:1px 10px;background-image:url(../img/folder-closed.png);background-repeat:no-repeat}div[data-tree-model] li .normal{padding:1px 10px;color:#000;background-image:url(../img/file.png);background-repeat:no-repeat}div[data-tree-model] li.selected{box-shadow:2px 3px 5px rgba(0,0,0,.6),inset 1px 10px 300px 51px #5cb85c!important}div[data-tree-model] span.selected{color:#fff!important;text-shadow:1px 1px #000!important;font-weight:700;padding:1px 5px}div[data-tree-model] li.changed{box-shadow:2px 3px 5px rgba(0,0,0,.6),inset 1px 10px 300px 51px rgba(250,250,210,1)}div[data-tree-model] span.changed{color:#000;text-shadow:1px 1px #fff;font-weight:700;padding:1px 5px}div[data-tree-model] span.loaded{text-decoration:underline;font-style:oblique}/*!
    22 * Bootstrap v3.3.6 (http://getbootstrap.com)
    33 * Copyright 2011-2015 Twitter, Inc.
  • branches/WebJobManager/HeuristicLab.Clients.Hive.WebJobManager/wwwroot/js/hubs/calendarhubber.js

    r13795 r13805  
    1414               vm.alertMessage = "No alerts";
    1515               vm.currentcal = [];
    16                $scope.permission = false;
     16               $scope.permissionview = false;
     17               $scope.resaddview = false;
    1718               vm.selectedEventId = -1;
    1819               vm.groups = [];
     
    100101                   $scope.$watch("treeview.currentNode", function (newValue, oldValue) {
    101102                       $scope.currentcal = [];
     103                       $scope.resaddview = false;
    102104                       $(".selected.ng-binding").addClass('loaded');
    103105                       $scope.selectedEventId = -1;
     
    112114                               $timeout(function () {
    113115                                   refreshPermissions();
     116                                   
    114117                                   $scope.currentcal = $scope.treeview.currentNode.calendar;
    115118                               }, 0);
    116119
    117120                           }
    118                        }
    119 
    120                    });
     121                           $scope.refreshAdds();
     122                       }
     123
     124                   });
     125               }
     126               $scope.refreshAdds = function() {
     127                   for (var i = 0; i < $scope.clients.length; i++) {
     128                       $scope.clients[i].add = false;
     129                       for (var j = 0; j < $scope.treeview.currentNode.children.length; j++) {
     130                           if ($scope.clients[i].Id === $scope.treeview.currentNode.children[j].Id)
     131                               $scope.clients[i].add = true;
     132                       }
     133                   }
    121134               }
    122135               function refreshPermissions() {
     
    650663               };
    651664
     665               $scope.menuchange = function (i) {
     666                   switch(i) {
     667                       case 0:
     668                           $scope.permissionview = false;
     669                           $scope.resaddview = false;
     670                           break;
     671                       case 1:
     672                           $scope.permissionview = true;
     673                           $scope.resaddview = false;
     674                           break;
     675                       case 2:
     676                           $scope.permissionview = false;
     677                           $scope.resaddview = true;
     678                           break;
     679                   }
     680               }
     681
    652682
    653683
  • branches/WebJobManager/HeuristicLab.Clients.Hive.WebJobManager/wwwroot/js/hubs/userinfohubber.js

    r13754 r13805  
    1 function resetPass(a){hubber.server.resetPassword(a)}var hubber=$.connection.userInfoHub;$(function(){$.connection.hub.logging=!0;var a=document.getElementById("userId").innerHTML;console.log(a),$.connection.hub.qs={userid:a},$.connection.hub.start(),hubber.client.showNewPass=function(a){$("#inppassreset").html("<label class=' control-label' style='text-align:left'>New password: "+a+"</label>")}});
     1function resetPass(a){hubber.server.resetPassword(a)}var hubber=$.connection.userInfoHub;$(function(){var a=document.getElementById("userId").innerHTML;console.log(a),$.connection.hub.qs={userid:a},$.connection.hub.start(),hubber.client.showNewPass=function(a){$("#inppassreset").html("<label class=' control-label' style='text-align:left'>An email has been sent to the user containing the new password</label>")}});
Note: See TracChangeset for help on using the changeset viewer.