Changeset 13782


Ignore:
Timestamp:
04/21/16 16:48:34 (5 years ago)
Author:
jlodewyc
Message:

#2582 Resource calendar and client group creation, control implemented

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

Legend:

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

    r13754 r13782  
    1 using HeuristicLab.Clients.Access.Administration;
     1using HeuristicLab.Clients.Access;
     2using HeuristicLab.Clients.Access.Administration;
    23using HeuristicLab.Clients.Hive.WebJobManager.Services;
    34using Microsoft.AspNet.Hosting;
     
    89using System.Linq;
    910using System.ServiceModel.Security;
     11using System.Threading;
    1012using System.Threading.Tasks;
    1113
     
    1719        private HiveServiceLocatorWeb serviceLocator;
    1820        private AccessAdministrationClient accessClient;
     21        private HiveAdminClientWeb adminClient;
    1922        private Guid userId;
    2023
     
    3740                userId = Guid.Parse(u);
    3841                serviceLocator = weblog.getServiceLocator(userId);
     42                adminClient = weblog.getAdminClient(userId);
    3943                accessClient = weblog.getAccessAdminClient(userId);
    4044                return serviceLocator.CheckLogin();
     
    5660            }
    5761        }
     62        [HttpPost]
     63        public IActionResult changeParent(string inpid, string inpidpar)
     64        {
     65            if (init())
     66            {
     67                var gid = Guid.Parse(inpid);
     68               
     69
     70                adminClient.Refresh();
     71                var tochange = adminClient.Resources.ToList().Find(x => x.Id == gid);
     72               
     73                if (inpidpar != null && inpidpar != "") {
     74                    Guid tempid = Guid.Parse(inpidpar);
     75                    while (tempid != null)
     76                    {
     77                        if (tempid != gid)
     78                        {
     79                            tempid = (Guid)adminClient.Resources.ToList().Find(x => x.Id == tempid).ParentResourceId;
     80                        }
     81                        else
     82                            break;
     83                    }
     84                    if(tempid == null)
     85                        tochange.ParentResourceId = Guid.Parse(inpidpar);
     86                }
     87                else
     88                    tochange.ParentResourceId = null;
     89                adminClient.Store(tochange, CancellationToken.None);
     90
     91                return RedirectToAction("Index", "Resource");
     92            }
     93            else
     94            {
     95                return RedirectToAction("Index", "Home");
     96            }
     97        }
     98        [HttpPost]
     99        public IActionResult deleteClientGroup(string inpid)
     100        {
     101            if (init())
     102            {
     103                var gid = Guid.Parse(inpid);
     104
     105                adminClient.Refresh();
     106                var group = adminClient.Resources.ToList().Find(x => x.Id == gid);
     107                var list = adminClient.Resources.ToList().FindAll(x => x.ParentResourceId == gid);
     108                foreach(var cl in list)
     109                {
     110                    cl.ParentResourceId = group.ParentResourceId;
     111                    adminClient.Store(cl, CancellationToken.None);
     112                }
     113                adminClient.Delete(group);
     114
     115                return RedirectToAction("Index", "Resource");
     116            }
     117            else
     118            {
     119                return RedirectToAction("Index", "Home");
     120            }
     121        }
     122
     123        [HttpPost]
     124        public IActionResult newClientGroup(string inpname, int inpheart, string inpparent, string[] clientstoadd)
     125        {
     126            if (init()) {
     127                adminClient.Refresh();
     128
     129                SlaveGroup sg = new SlaveGroup();
     130                sg.Id = Guid.Empty;
     131                sg.Name = inpname;
     132                sg.HbInterval = inpheart;
     133                if (inpparent != "")
     134                    sg.ParentResourceId = Guid.Parse(inpparent);
     135                sg.OwnerUserId = serviceLocator.getHiveServiceClient().GetUserIdByUsername(serviceLocator.getHiveServiceClient().ClientCredentials.UserName.UserName);
     136                adminClient.Store(sg, CancellationToken.None);
     137                adminClient.Refresh();
     138                var id = adminClient.Resources.ToList().Find(x => x.Name == inpname).Id;
     139                foreach(var s in clientstoadd)
     140                {
     141                    var cid = Guid.Parse(s);
     142                    var client = adminClient.Resources.ToList().Find(x => x.Id == cid);
     143                    client.ParentResourceId = id;
     144                    adminClient.Store(client, CancellationToken.None);
     145                }
     146
     147                return RedirectToAction("Index", "Resource");
     148            }
     149            else
     150            {
     151                return RedirectToAction("Index", "Home");
     152            }
     153        }
    58154    }
    59155}
  • branches/WebJobManager/HeuristicLab.Clients.Hive.WebJobManager/Hubs/CalendarHub.cs

    r13775 r13782  
    4747            var down = JsonConvert.SerializeObject(adminClient.Downtimes);
    4848            Clients.Caller.processDowntime(id, down);
     49        }
     50        public void toggleDisposable(string id)
     51        {
     52            loader();
     53            adminClient.Refresh();
     54            Guid c = Guid.Parse(id);
     55            var obj = adminClient.Resources.ToList().Find(x => x.Id == c);
     56            ((Slave)(obj)).IsDisposable = !((Slave)(obj)).IsDisposable;
     57            adminClient.Store(obj, CancellationToken.None);
     58            Clients.Caller.processDispose( ((Slave)(obj)).IsDisposable);
     59
    4960        }
    5061        public void saveCalendar(string id, string[] del, string[][] add, string[][] upd, bool fresh, bool last)
  • branches/WebJobManager/HeuristicLab.Clients.Hive.WebJobManager/Scripts/Hubs/CalendarHubber.js

    r13775 r13782  
    1515               vm.currentcal = [];
    1616               vm.selectedEventId = -1;
    17 
     17               vm.groups = [];
     18               vm.clients = [];
    1819               vm.init = function () {
    1920
     
    3334                   };
    3435                   hubber.client.savingCurrentDone = function () {
     36                       vm.calendarSaver = false;
    3537                       $scope.clearCurrentCalendar();
    3638                       $scope.$apply();
    3739                   };
    3840                   hubber.client.savingAllDone = function () {
     41                       vm.calendarSaver = false;
    3942                       clearAllCalendarsFunc();
    4043                       $scope.$apply();
    4144                   };
     45                   hubber.client.processDispose = function (disp) {
     46                       vm.treeview.currentNode.IsDisposable = disp;
     47                       $scope.calendarDispose = false;
     48                       $scope.$apply();
     49                   }
    4250                   hubber.client.processDowntime = function (id, down) {
    4351                       var json = JSON.parse(down);
     
    8391                       $(".selected.ng-binding").addClass('loaded');
    8492                       $scope.selectedEventId = -1;
    85                        if ($scope.treeview.currentNode != null) {
     93                       if ($scope.treeview.currentNode != null && $scope.treeview.currentNode.Id != undefined) {
    8694                           if ($scope.treeview.currentNode.calendar.length === 0) {
    8795                               hubber.server.requestDownTime(vm.treeview.currentNode.Id);
     
    98106
    99107                   });
     108               }
     109               $scope.clearTreeSelect = function () {
     110                   if (vm.treeview.currentNode != undefined) {
     111                       vm.treeview.currentNode.selected = undefined;
     112                       vm.treeview.currentNode = undefined;
     113                       vm.selectedEventId = -1;
     114                   }
    100115               }
    101116               $scope.buildTree = function () {
     
    103118                   vm.temptree = [];
    104119                   vm.top = false;
     120                   var ungrouped = {
     121                       children: [],
     122                       Name: 'Ungrouped'
     123                   }
    105124                   for (; vm.data.length > 0;) {
    106125
    107                        if (vm.data[0].ParentResourceId == null) {
     126                       if (vm.data[0].ParentResourceId == null && vm.data[0].IsDisposable !== undefined) {
    108127                           var curr = $scope.seekChildren(vm.data.splice(0, 1)[0]);
     128                           vm.clients.push(curr);
     129                           ungrouped.children.push(curr);
     130                       }
     131                       else if (vm.data[0].ParentResourceId == null) {
     132                           var curr = $scope.seekChildren(vm.data.splice(0, 1)[0]);
     133                           vm.groups.push(curr);
    109134                           vm.tree.push(curr);
    110135                       }
    111136                       else {
    112137                           var curr = $scope.seekChildren(vm.data.splice(0, 1)[0]);
     138                           if (curr.IsDisposable !== undefined)
     139                               vm.clients.push(curr);
     140                           else
     141                               vm.groups.push(curr);
    113142                           vm.temptree.push(curr);
    114143                       }
    115144                   }
     145                   vm.tree.push(ungrouped);
    116146
    117147               };
     
    134164                   for (var t = 0; t < vm.data.length;) {
    135165                       if (current.Id == vm.data[t].ParentResourceId) {
     166                           if (vm.data[t].IsDisposable !== undefined)
     167                               vm.clients.push(vm.data[t]);
     168                           else
     169                               vm.groups.push(vm.data[t]);
    136170                           current.children.push(vm.data.splice(t, 1)[0]);
    137171                       }
     
    145179                   return current;
    146180               }
     181
     182               $scope.toggleDisposable = function () {
     183                   $scope.calendarDispose = true;
     184                   hubber.server.toggleDisposable(vm.treeview.currentNode.Id);
     185               }
     186
    147187               function collectInfoToSave(node, refresh, last) {
    148188                   var arr = node.calendar.down[0];
     
    164204                               "" + Date.parse(arr[i].rec.end),
    165205                               arr[i].rec.days.join(",")
    166                                
     206
    167207
    168208                           ]);
     
    181221                               "" + Date.parse(arr[i].rec.end),
    182222                               arr[i].rec.days.join(",")
    183                                
     223
    184224                           ]);
    185225                       }
     
    189229               }
    190230               $scope.saveCurrentCalendar = function () {
     231                   vm.calendarSaver = true;
    191232                   collectInfoToSave(vm.treeview.currentNode, true, false);
    192233                   //true for refresh, false for showing it's only one calendar saved.
    193234               }
    194235               $scope.saveAllCalendars = function () {
     236
    195237                   $scope.allSave = [];
    196238                   for (var i = 0; i < $scope.tree.length; i++)
     
    205247                       plain: true
    206248                   }).then(function (success) {
     249                       vm.calendarSaver = true;
    207250                       for (var i = 0; i < $scope.allSave.length; i++) {
    208251                           if (i >= $scope.allSave.length - 1)
     
    255298                   $scope.currentcal = [];
    256299                   for (var i = 0; i < $scope.tree.length; i++)
    257                        removeCalendarsRecurse($scope.tree[i]);
     300                       clearCalendarsRecurse($scope.tree[i]);
    258301                   hubber.server.requestDownTime(vm.treeview.currentNode.Id);
    259302                   $(".selected.ng-binding").addClass('loaded');
    260303               }
    261                function removeCalendarsRecurse(node) {
     304               function clearCalendarsRecurse(node) {
    262305
    263306                   node.calendar = [];
     
    265308                   node.changes = false;
    266309                   for (var i = 0; i < node.children.length; i++) {
    267                        removeCalendarsRecurse(node.children[i]);
    268                    }
    269                }
    270 
     310                       clearCalendarsRecurse(node.children[i]);
     311                   }
     312               }
     313               $scope.deleteAllEvents = function () {
     314                   vm.calendarDeleter = true;
     315                   vm.selectedEventId = -1;
     316                   var node = vm.treeview.currentNode.calendar.down[0];
     317                   for (var i = 0; i < node.length;) {
     318                       if (node[i].id != '00000000-0000-0000-0000-000000000000')
     319                           vm.treeview.currentNode.todelete.push(node[i].id);
     320                       $scope.setChanged(vm.selectedEventId);
     321                       node.splice(i, 1);
     322                   }
     323                   vm.calendarDeleter = false;
     324                   ngDialog.open({
     325                       template:
     326                        '<p>All events have been deleted. Save the changes to confirm deletion, clearing will restore all the events from the server</p>',
     327                       plain: true
     328                   });
     329               }
    271330               $scope.deleteAllPreviousEvents = function () {
     331                   vm.calendarDeleter = true;
    272332                   vm.selectedEventId = -1;
    273333                   var node = vm.treeview.currentNode.calendar.down[0];
     
    282342                           i++;
    283343                   }
     344                   vm.calendarDeleter = false;
    284345                   ngDialog.open({
    285346                       template:
     
    329390                   vm.selectedEventId = vm.treeview.currentNode.calendar.down[0].length - 1;
    330391                   vm.setChanged(vm.selectedEventId);
    331                    //  $("#resourcecalendar").fullCalendar('refetchEvents');
     392                   $scope.currentcal = [];
     393                   $scope.currentcal = vm.treeview.currentNode.calendar;
     394
    332395
    333396               }
     
    342405               $scope.eventClick = function (date, jsEvent, view) {
    343406                   vm.selectedEventId = checkId(date._id);
     407               };
     408               $scope.eventClickBtn = function (id) {
     409                   vm.selectedEventId = checkId(id);
     410                   vm.goToDate();
    344411               };
    345412               /* alert on Drop */
     
    381448
    382449               };
     450               $scope.removeList = function (id) {
     451                   var index = checkId(id);
     452                   vm.selectedEventId = -1;
     453                   vm.setChanged(vm.selectedEventId);
     454                   if (vm.treeview.currentNode.calendar.down[0][index].id != "00000000-0000-0000-0000-000000000000") {
     455                       vm.treeview.currentNode.todelete.push(vm.treeview.currentNode.calendar.down[0][index].id);
     456                   }
     457                   vm.treeview.currentNode.calendar.down[0].splice(index, 1);
     458
     459
     460               };
    383461
    384462               $scope.checkDateStartEnd = function () {
    385463                   if ($scope.currentcal.down[0][vm.selectedEventId].rec.start > $scope.currentcal.down[0][vm.selectedEventId].rec.end ||
    386464                       $scope.currentcal.down[0][vm.selectedEventId].rec.end === undefined) {
    387                        
     465
    388466                       $scope.currentcal.down[0][vm.selectedEventId].rec.end = new Date($scope.currentcal.down[0][vm.selectedEventId].rec.start);
    389                        
     467
    390468                   }
    391469                   if ($scope.currentcal.down[0][vm.selectedEventId].rec.start < Date.now())
    392470                       $scope.currentcal.down[0][vm.selectedEventId].rec.start = new Date();
    393                   }
     471               }
    394472               //pushes all changes to other recurs
    395473               $scope.pushRecurChanges = function (recid) {
     
    415493                               }
    416494                               else {
    417                                    
     495
    418496                                   arr[i].start.setHours(ob.start.getHours(), ob.start.getMinutes());
    419497                                   arr[i].end.setHours(ob.end.getHours(), ob.end.getMinutes());
     
    439517                                   loop2:
    440518                                       for (var i = 0; i < arr.length; i++) {
    441                                            
     519
    442520                                           if (arr[i].rec.recid === recid) {
    443                                                var dend = (d+1000 * 3600 * 24);
     521                                               var dend = (d + 1000 * 3600 * 24);
    444522                                               if (arr[i].start.getTime() >= d &&
    445523                                                   arr[i].end.getTime() <= dend) {
     
    449527                                           }
    450528                                       }
    451  
     529
    452530                                   var ts = new Date(d);
    453531                                   ts.setHours(new Date(ob.start).getHours(), new Date(ob.start).getMinutes());
     
    465543
    466544                               }
    467                                
     545
    468546                               d += (1000 * 3600 * 24);// 1 day
    469                              
     547
    470548                           }
    471549                   });
     
    491569               }
    492570
     571               $scope.goToDate = function () {
     572                   $("#resourcecalendar").fullCalendar('gotoDate', vm.currentcal.down[0][vm.selectedEventId].start);
     573               }
    493574               /* Render Tooltip */
    494575               $scope.eventRender = function (event, element, view) {
     
    508589                       header: {
    509590                           left: 'title',
    510                            center: '',
     591                           center: 'agendaWeek, agendaDay',
    511592                           right: 'today prev,next'
    512593                       },
     
    520601
    521602
    522                    }
    523                };
    524 
    525 
    526 
     603
     604                   }
     605               };
     606
     607
     608
     609           }).filter('disp', function () {
     610               return function (input) {
     611                   return input ? 'Disposable' : 'Not disposable';
     612               }
     613           }).directive('animateOnChange', function ($timeout) {
     614               return function (scope, element, attr) {
     615                   scope.$watch(attr.animateOnChange, function (nv, ov) {
     616
     617                       if (nv != ov) {
     618                           if (scope.currentcal.down[0][scope.selectedEventId].title === "Unavailable") {
     619                               element.addClass('changed');
     620                               $timeout(function () {
     621                                   element.removeClass('changed');
     622                               }, 250); // Could be enhanced to take duration as a parameter
     623                           }
     624                           else {
     625                               element.addClass('changedshut');
     626                               $timeout(function () {
     627                                   element.removeClass('changedshut');
     628                               }, 250); // Could be enhanced to take duration as a parameter
     629                           }
     630                       }
     631                   });
     632               };
    527633           });
    528634
  • branches/WebJobManager/HeuristicLab.Clients.Hive.WebJobManager/Scripts/Styling/StyleSheet.css

    r13758 r13782  
    202202        font-style:oblique;
    203203    }
     204    [animate-on-change] {
     205  transition: all 1s;
     206  -webkit-transition: all 1s;
     207}
     208[animate-on-change].changed {
     209  background-color: lightblue;
     210  transition: none;
     211  -webkit-transition: none;
     212}
     213[animate-on-change].changedshut {
     214  background-color: lightsalmon;
     215  transition: none;
     216  -webkit-transition: none;
     217}
  • branches/WebJobManager/HeuristicLab.Clients.Hive.WebJobManager/Services/Imports/HiveServiceLocatorWeb.cs

    r13739 r13782  
    3838
    3939
    40         #region #unknownCalls
     40
    4141        public void CallHiveService(Action<IHiveService> call)
    4242        {
     
    8080            }
    8181        }
    82         #endregion unknown
    8382
    8483        /// <summary>
  • branches/WebJobManager/HeuristicLab.Clients.Hive.WebJobManager/Views/Resource/Index.cshtml

    r13775 r13782  
    55    @Html.Partial("Navbar", new HeuristicLab.Clients.Hive.WebJobManager.ViewModels.NavbarViewModel("Resource"))
    66
    7    
     7
    88
    99    <div class="col-sm-4">
     10        <div class="btn btn-block btn-success" ng-click="clearTreeSelect()">Add group</div>
    1011        <div data-angular-treeview="true"
    1112             data-tree-id="treeview"
     
    1718        </div>
    1819    </div>
    19     <div ng-if="treeview.currentNode" class="col-sm-8 panel  panel-primary" style="margin-bottom:200px">
    20         <div class="row panel-heading">
    21             <h3>{{treeview.currentNode.Name}} <span ng-if="treeview.currentNode.IsDisposable === undefined"> - Client group</span></h3>
    22             <table class="table">
    23                 <tbody>
    24                     <tr>
    25                         <td>Heartbeat</td>
    26                         <td>
    27                             Every {{treeview.currentNode.HbInterval}} sec
    28                             <span ng-if="treeview.currentNode.IsDisposable !== undefined">
    29                                 - Last beat {{treeview.currentNode.LastHeartbeat | date:'HH:mm dd/MM/yyyy' }}
    30                             </span>
    31                         </td>
    32                     </tr>
    33                     <tr>
    34                         <td>Name</td>
    35                         <td>{{treeview.currentNode.Name}}</td>
    36                     </tr>
    37                     <tr>
    38                         <td>Id</td>
    39                         <td>{{treeview.currentNode.Id}}</td>
    40                     </tr>
    41                     <tr>
    42                         <td>Disposable</td>
    43                         <td><input type="checkbox" ng-checked="treeview.currentNode.IsDisposable" /></td>
    44                     </tr>
    45                 </tbody>
    46                 <tbody ng-if="treeview.currentNode.IsDisposable !== undefined">
    47                     <tr>
    48                         <td>Cores (free/total)</td>
    49                         <td>{{treeview.currentNode.FreeCores}} | {{treeview.currentNode.Cores}}</td>
    50 
    51 
    52                     </tr>
    53                     <tr>
    54                         <td>Memory (free/total)</td>
    55                         <td>{{treeview.currentNode.FreeMemory}} MB | {{treeview.currentNode.Memory}} MB</td>
    56                     </tr>
    57 
    58                 </tbody>
    59             </table>
     20    <div ng-if="treeview.currentNode && treeview.currentNode.Id !== undefined" class="col-sm-8 panel  panel-primary" style="margin-bottom:200px">
     21        <div class="row panel-heading"
     22             style="box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);
     23                            text-shadow:2px 2px black;">
     24            <h3>
     25                {{treeview.currentNode.Name}}
     26                <span ng-if="treeview.currentNode.IsDisposable === undefined"> - Client group</span>
     27                <a ng-if="treeview.currentNode.IsDisposable !== undefined"
     28                   class="btn pull-right"
     29                   style="box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);
     30                            text-shadow:2px 2px black;font-weight:bold;margin-bottom:5px"
     31                   ng-class="{ 'btn-success': treeview.currentNode.IsDisposable, 'btn-warning': !treeview.currentNode.IsDisposable }"
     32                   ng-click="toggleDisposable()">
     33                    <span ng-if="calendarDispose"><i class="fa fa-save fa-spin"></i> </span> {{ treeview.currentNode.IsDisposable | disp}}
     34                </a>
     35            </h3>
     36            <form method="post"
     37                  asp-action="deleteClientGroup"
     38                  ng-init="checkDel = false"
     39                  asp-controller="Resource"
     40                  enctype="multipart/form-data"
     41                  class="row panel-heading"
     42                  style="padding:10px">
     43                <table class="table" style="margin-bottom:0px">
     44                    <tbody>
     45                        <tr>
     46                            <td>Heartbeat</td>
     47                            <td>
     48                                Every {{treeview.currentNode.HbInterval}} sec
     49                                <span ng-if="treeview.currentNode.IsDisposable !== undefined">
     50                                    - Last beat {{treeview.currentNode.LastHeartbeat | date:'HH:mm dd/MM/yyyy' }}
     51                                </span>
     52                            </td>
     53                        </tr>
     54                        <tr>
     55                            <td>Name</td>
     56                            <td>{{treeview.currentNode.Name}}</td>
     57                        </tr>
     58                        <tr>
     59                            <td>Id</td>
     60                            <td>{{treeview.currentNode.Id}}</td>
     61                        </tr>
     62                        <tr ng-if="treeview.currentNode.IsDisposable === undefined">
     63
     64                            <td>
     65
     66                                <input style="display:none" type="text" id="inpid" name="inpid" value="{{treeview.currentNode.Id}}" />
     67                                <input type="checkbox" ng-model="checkDel" /> I want to delete this group
     68                            </td>
     69                            <td>
     70                                <button type="submit"
     71                                        id="inpsaver"
     72                                        ng-disabled="!checkDel"
     73                                        class="btn btn-danger">
     74                                    <i class="fa fa-trash-o"></i>
     75                                    Delete group (irriversible action!)
     76                                </button>
     77
     78                            </td>
     79
     80                        </tr>
     81                    </tbody>
     82                    <tbody ng-if="treeview.currentNode.IsDisposable !== undefined">
     83                        <tr>
     84                            <td>Cores (free/total)</td>
     85                            <td>{{treeview.currentNode.FreeCores}} / {{treeview.currentNode.Cores}} @@ {{treeview.currentNode.CpuSpeed/1000 | number:1}} GHz</td>
     86
     87
     88                        </tr>
     89                        <tr>
     90                            <td>Memory (free/total)</td>
     91                            <td>{{treeview.currentNode.FreeMemory/1024 | number:1}} GB / {{treeview.currentNode.Memory/1024 | number:1}} GB</td>
     92                        </tr>
     93
     94                    </tbody>
     95                </table>
     96            </form>
     97            <form method="post"
     98                  asp-action="changeParent"
     99                  asp-controller="Resource"
     100                  enctype="multipart/form-data"
     101                  class="row"
     102                  style="padding:10px"
     103                  >
     104                <input style="display:none" type="text" id="inpid" name="inpid" value="{{treeview.currentNode.Id}}" />
     105
     106                <span style="padding:0px" class="col-sm-4">Change parent resource: </span>
     107               
     108                <select class="form-control col-sm-5"
     109                        style="width:200px"
     110                        id="inpidpar"
     111                        name="inpidpar"
     112                        ng-model="treeview.currentNode.ParentResourceId">
     113                    <option value="">None</option>
     114                    <option ng-repeat="group in groups | orderBy:'Name'"
     115                            value="{{group.Id}}"
     116                            ng-if="group.Id !=treeview.currentNode.Id && group.ParentResourceId != treeview.currentNode.Id">
     117                        {{group.Name}}
     118                    </option>
     119
     120                </select>
     121                <button type="submit"
     122                        id="inpsaver"
     123                        class="btn btn-warning col-sm-3 pull-right">
     124                    <i class="fa fa-save"></i>
     125                    Change parent
     126                </button>
     127            </form>
    60128        </div>
    61129        <div class="panel-body row" style="text-align:center">
    62             <div class="row" style="padding-bottom:30px;">
    63                 <button class="btn btn-success" ng-click="saveCurrentCalendar()">Save current changes</button>
    64                 <button class="btn btn-success" ng-click="saveAllCalendars()">Save all changes</button>
    65                 <button class="btn btn-warning" ng-click="clearCurrentCalendar()">Clear current changes</button>
    66                 <button class="btn btn-warning" ng-click="clearAllCalendars()">Clear all changes</button>
    67             </div>
    68             <div class="row" style="padding-bottom:30px;">
    69                 <button class="btn btn-info" ng-click="deleteAllPreviousEvents()">Delete all previous events to date</button>
    70             </div>
     130
    71131            <i ng-if="currentcal.length  === 0" class="fa fa-cog fa-5x fa-spin"></i>
    72132            <div ng-if="currentcal.length != 0"
     
    76136                 class="span8 calendar"
    77137                 ng-model="currentcal.down"></div>
    78             <table ng-if="selectedEventId != -1" class="table">
    79                 <tr>
    80                     <th colspan="2"> Selected event</th>
    81 
     138            <table ng-if="selectedEventId != -1"
     139                   animate-on-change="selectedEventId"
     140                   class="table">
     141                <tr>
     142                    <th> Selected event</th>
     143                    <th>
     144                        <div class="btn btn-default"
     145                             ng-click="goToDate()"
     146                             ng-style="{'background-color':currentcal.down[0][selectedEventId].color }"
     147                             style="color:white;box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);
     148                            text-shadow:2px 2px black;font-weight:bold;">
     149                            <i class="fa fa-calendar"></i> Go to date
     150                        </div>
     151                    </th>
    82152                </tr>
    83153                <tr>
     
    119189                    </td>
    120190                    <td>
    121                         <input type="date" 
    122                                ng-model="currentcal.down[0][selectedEventId].rec.start" 
     191                        <input type="date"
     192                               ng-model="currentcal.down[0][selectedEventId].rec.start"
    123193                               ng-change="checkDateStartEnd()" />
    124194                    </td>
    125195                </tr>
    126                 <tr ng-if="currentcal.down[0][selectedEventId].rec.recurrence" >
     196                <tr ng-if="currentcal.down[0][selectedEventId].rec.recurrence">
    127197                    <td>
    128198                        End
    129199                    </td>
    130200                    <td>
    131                         <input type="date" 
    132                                ng-model="currentcal.down[0][selectedEventId].rec.end" 
    133                                ng-change="checkDateStartEnd()" 
    134                                min="{{currentcal.down[0][selectedEventId].rec.start | date:'yyyy-MM-dd'}}"/>
    135                     </td>
    136                 </tr>
    137                
     201                        <input type="date"
     202                               ng-model="currentcal.down[0][selectedEventId].rec.end"
     203                               ng-change="checkDateStartEnd()"
     204                               min="{{currentcal.down[0][selectedEventId].rec.start | date:'yyyy-MM-dd'}}" />
     205                    </td>
     206                </tr>
     207
    138208                <tr ng-if="currentcal.down[0][selectedEventId].rec.recurrence">
    139209                    <td colspan="2">
     
    146216                        <label class="checkbox-inline"><input type="checkbox" ng-model="currentcal.down[0][selectedEventId].rec.days[0]">Sunday</label>
    147217                    </td>
    148                    
     218
    149219                </tr>
    150220                <tr>
     
    153223                        <button class="btn btn-info"
    154224                                ng-click="pushRecurChanges(currentcal.down[0][selectedEventId].rec.recid)"
    155                                 ng-if="currentcal.down[0][selectedEventId].rec.recid != '0' &&
     225                                style="box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);
     226                            text-shadow:2px 2px black;"
     227                                ng-if="currentcal.down[0][selectedEventId].rec.recid != '0' &&
    156228                                currentcal.down[0][selectedEventId].rec.recid != '00000000-0000-0000-0000-000000000000' &&
    157229                                currentcal.down[0][selectedEventId].changed">
     
    159231                        </button>
    160232                        <button class="btn btn-danger"
     233                                style="box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);
     234                            text-shadow:2px 2px black;"
    161235                                ng-click="remove(selectedEventId)">
    162236                            <i class="fa fa-trash-o"></i>
     
    164238                        </button>
    165239                        <button class="btn btn-danger"
     240                                style="box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);
     241                            text-shadow:2px 2px black;"
    166242                                ng-click="deleteAllRecurrences(currentcal.down[0][selectedEventId].rec.recid)"
    167243                                ng-if="currentcal.down[0][selectedEventId].rec.recid != '0'
     
    173249            </table>
    174250            <table ng-if="selectedEventId === -1" class="table">
    175             <tr>
    176                 <th colspan="2"> Select an event to show information</th>
    177 
    178             </tr>
    179             <tr>
    180                 <td>Time / Select an event</td>
    181                    </tr>
    182             <tr>
    183                 <td>Status / Select an event</td>
    184             </tr>
     251                <tr>
     252                    <th colspan="2"> Select an event to show information</th>
     253
     254                </tr>
     255                <tr>
     256                    <td>Time / Select an event</td>
     257                </tr>
     258                <tr>
     259                    <td>Status / Select an event</td>
     260                </tr>
    185261            </table>
     262            <div ng-if="calendarSaver">
     263                <i class="fa fa-save fa-4x fa-spin"></i>
     264            </div>
     265            <div ng-if="calendarDeleter">
     266                <i class="fa fa-trash-o fa-4x fa-spin"></i>
     267            </div>
     268            <div class="row">
     269                <h3>Current calendar - actions</h3>
     270                <div class="btn-group btn-group-justified"
     271                     role="group"
     272                     style="padding-bottom:20px;">
     273
     274                    <div ng-if="treeview.currentNode.changes"
     275                         class="btn btn-success"
     276                         ng-click="saveCurrentCalendar()"
     277                         style="box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);
     278                            text-shadow:2px 2px black;">
     279                        Save current changes
     280                    </div>
     281                    <div ng-if="treeview.currentNode.changes"
     282                         class="btn btn-warning"
     283                         ng-click="clearCurrentCalendar()"
     284                         style="box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);
     285                            text-shadow:2px 2px black;">
     286                        Clear current changes
     287                    </div>
     288                    <div class="btn btn-danger"
     289                         ng-click="deleteAllPreviousEvents()"
     290                         style="box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);
     291                            text-shadow:2px 2px black;">
     292                        Delete past events
     293                    </div>
     294                    <div class="btn btn-danger"
     295                         ng-click="deleteAllEvents()"
     296                         style="box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);
     297                            text-shadow:2px 2px black;">
     298                        Delete all events
     299                    </div>
     300                </div>
     301            </div>
     302            <div class="row">
     303                <h3>All loaded calendars - actions</h3>
     304                <div class="btn-group btn-group-justified"
     305                     role="group"
     306                     style="padding-bottom:20px;">
     307
     308                    <div class="btn btn-success"
     309                         ng-click="saveAllCalendars()"
     310                         style="box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);
     311                            text-shadow:2px 2px black;">
     312                        Save all changes
     313                    </div>
     314
     315                    <div class="btn btn-warning"
     316                         ng-click="clearAllCalendars()"
     317                         style="box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);
     318                            text-shadow:2px 2px black;">
     319                        Clear all changes
     320                    </div>
     321                </div>
     322            </div>
     323
    186324        </div>
    187325
    188326        <div class="row panel-footer">
     327            <h2>All events </h2><h5>(sorted by changed and start date)</h5>
     328            <div class="row" ng-repeat="ev in currentcal.down[0] | orderBy:['!changed','start'] track by $index">
     329                <div class="btn-group-justified btn-block">
     330
     331                    <div class="btn btn-default" ng-style="{'background-color': ev.color}"
     332                         ng-click="eventClickBtn(ev._id)"
     333                         style="width:6%;color:white;
     334                            box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);text-shadow:2px 2px black;">
     335                        {{ev.title }}
     336                        <span ng-if="!ev.allDay">
     337                            from {{ev.start | date : 'HH:mm dd/MM/yy' : 'utc'}}
     338                            <span ng-if="ev.end">
     339                                to {{ev.end | date : 'HH:mm dd/MM/yy': 'utc'}}
     340                            </span>
     341                        </span>
     342                        <span ng-if="ev.allDay">
     343                            all day from {{ev.start | date : 'dd/MM/yy' : 'utc'}}
     344                            <span ng-if="ev.end">
     345                                to {{ev.end | date : 'dd/MM/yy': 'utc'}}
     346                            </span>
     347                        </span>
     348                        <span ng-if="ev.rec.recurrence">
     349                            | recurring event
     350                        </span>
     351                    </div>
     352                    <a id="del"
     353                       style="box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);
     354                            text-shadow:2px 2px black;"
     355                       class='btn btn-group btn-danger'
     356                       ng-click="removeList(ev._id)">
     357                        <span class='glyphicon glyphicon-trash' aria-hidden='true'></span>
     358                    </a>
     359                </div>
     360
     361            </div>
     362
     363        </div>
     364    </div>
     365    <div ng-show="treeview.currentNode === undefined"
     366         style="margin-bottom:200px">
     367        <form method="post"
     368              ng-init="newName = ''"
     369              asp-action="newClientGroup"
     370              asp-controller="Resource"
     371              enctype="multipart/form-data"
     372              class="col-sm-8 panel  panel-primary">
     373            <div class="row panel-heading"
     374                 style="box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);
     375                            text-shadow:2px 2px black;">
     376                <h3>
     377                    Add new client group
     378                </h3>
     379                <table class="table">
     380                    <tbody>
     381                        <tr>
     382                            <td>Heartbeat</td>
     383                            <td>
     384                                <i class="fa fa-clock-o fa-2x pull-left"></i> <input type="number" class="form-control" style="width:70px" name="inpheart" id="inpheart" value="60" placeholder="60" />
     385
     386
     387                            </td>
     388                        </tr>
     389                        <tr>
     390                            <td>Name</td>
     391                            <td><input type="text" class="form-control" id="inpname" name="inpname" ng-model="newName" placeholder="Group name" /></td>
     392                        </tr>
     393                        <tr>
     394                            <td>Assign parent group</td>
     395                            <td>
     396                                <select class="form-control" id="inpparent" name="inpparent">
     397                                    <option value="">None</option>
     398                                    <option ng-repeat="group in groups | orderBy:'Name'" value="{{group.Id}}">{{group.Name}}</option>
     399
     400                                </select>
     401                            </td>
     402                        </tr>
     403                    </tbody>
     404
     405                </table>
     406                <button type="submit"
     407                        id="inpsaver"
     408                        ng-disabled="newName === ''"
     409                        class="btn btn-success">
     410                    <i class="fa fa-save"></i>
     411                    Add {{newName}} group
     412                </button>
     413            </div>
     414            <div class="panel-body row">
     415                <h3>Choose clients </h3>
     416                <h5>(This will overwrite the group set for these clients)</h5>
     417                <table>
     418                    <tr ng-repeat="client in clients  | orderBy:['Name'] track by $index" class="checkbox col-md-6 col-lg-4">
     419                        <td>
     420                            <label>
     421                                <input type="checkbox"
     422                                       name="clientstoadd"
     423                                       value="{{client.Id}}">
     424                                <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
     425                            </label>
     426                        </td>
     427                    </tr>
     428                </table>
     429            </div>
     430        </form>
     431    </div>
     432
     433    <div ng-if="treeview.currentNode !== undefined && treeview.currentNode.Id === undefined"
     434         class="col-sm-8 panel  panel-primary"
     435         style="margin-bottom:200px">
     436        <div class="row panel-heading"
     437             style="box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);
     438                            text-shadow:2px 2px black;">
     439            <h2>
     440                Ungrouped
     441            </h2>
     442            <h3>
     443                All unassigned clients arrive here. Assign them to a group to remove them from this group.
     444            </h3>
    189445
    190446        </div>
  • branches/WebJobManager/HeuristicLab.Clients.Hive.WebJobManager/wwwroot/css/site.min.css

    r13758 r13782  
    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 i,div[data-tree-model] li span{cursor:pointer}.fc table,table{border-spacing: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}div[data-tree-model] li .changed{background-color:#ff0;font-weight:700;padding:1px 5px}div[data-tree-model] li .loaded{text-decoration:underline;font-style:oblique}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:Tahoma;font-size:13px;color:#555;text-decoration:none}div[data-tree-model] ul{margin:0;padding:0;list-style:none;border:none;overflow:hidden}div[data-tree-model] li{position:relative;padding:0 0 0 20px;line-height:20px}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;background-image:url(../img/file.png);background-repeat:no-repeat}div[data-tree-model] li .selected{background-color:#adf;font-weight:700;padding:1px 5px}/*!
     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 i,div[data-tree-model] li span{cursor:pointer}.fc table,table{border-spacing: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}div[data-tree-model] li .changed{background-color:#ff0;font-weight:700;padding:1px 5px}div[data-tree-model] li .loaded{text-decoration:underline;font-style:oblique}[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}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:Tahoma;font-size:13px;color:#555;text-decoration:none}div[data-tree-model] ul{margin:0;padding:0;list-style:none;border:none;overflow:hidden}div[data-tree-model] li{position:relative;padding:0 0 0 20px;line-height:20px}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;background-image:url(../img/file.png);background-repeat:no-repeat}div[data-tree-model] li .selected{background-color:#adf;font-weight:700;padding:1px 5px}/*!
    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

    r13775 r13782  
    1515               vm.currentcal = [];
    1616               vm.selectedEventId = -1;
    17 
     17               vm.groups = [];
     18               vm.clients = [];
    1819               vm.init = function () {
    1920
     
    3334                   };
    3435                   hubber.client.savingCurrentDone = function () {
     36                       vm.calendarSaver = false;
    3537                       $scope.clearCurrentCalendar();
    3638                       $scope.$apply();
    3739                   };
    3840                   hubber.client.savingAllDone = function () {
     41                       vm.calendarSaver = false;
    3942                       clearAllCalendarsFunc();
    4043                       $scope.$apply();
    4144                   };
     45                   hubber.client.processDispose = function (disp) {
     46                       vm.treeview.currentNode.IsDisposable = disp;
     47                       $scope.calendarDispose = false;
     48                       $scope.$apply();
     49                   }
    4250                   hubber.client.processDowntime = function (id, down) {
    4351                       var json = JSON.parse(down);
     
    8391                       $(".selected.ng-binding").addClass('loaded');
    8492                       $scope.selectedEventId = -1;
    85                        if ($scope.treeview.currentNode != null) {
     93                       if ($scope.treeview.currentNode != null && $scope.treeview.currentNode.Id != undefined) {
    8694                           if ($scope.treeview.currentNode.calendar.length === 0) {
    8795                               hubber.server.requestDownTime(vm.treeview.currentNode.Id);
     
    98106
    99107                   });
     108               }
     109               $scope.clearTreeSelect = function () {
     110                   if (vm.treeview.currentNode != undefined) {
     111                       vm.treeview.currentNode.selected = undefined;
     112                       vm.treeview.currentNode = undefined;
     113                       vm.selectedEventId = -1;
     114                   }
    100115               }
    101116               $scope.buildTree = function () {
     
    103118                   vm.temptree = [];
    104119                   vm.top = false;
     120                   var ungrouped = {
     121                       children: [],
     122                       Name: 'Ungrouped'
     123                   }
    105124                   for (; vm.data.length > 0;) {
    106125
    107                        if (vm.data[0].ParentResourceId == null) {
     126                       if (vm.data[0].ParentResourceId == null && vm.data[0].IsDisposable !== undefined) {
    108127                           var curr = $scope.seekChildren(vm.data.splice(0, 1)[0]);
     128                           vm.clients.push(curr);
     129                           ungrouped.children.push(curr);
     130                       }
     131                       else if (vm.data[0].ParentResourceId == null) {
     132                           var curr = $scope.seekChildren(vm.data.splice(0, 1)[0]);
     133                           vm.groups.push(curr);
    109134                           vm.tree.push(curr);
    110135                       }
    111136                       else {
    112137                           var curr = $scope.seekChildren(vm.data.splice(0, 1)[0]);
     138                           if (curr.IsDisposable !== undefined)
     139                               vm.clients.push(curr);
     140                           else
     141                               vm.groups.push(curr);
    113142                           vm.temptree.push(curr);
    114143                       }
    115144                   }
     145                   vm.tree.push(ungrouped);
    116146
    117147               };
     
    134164                   for (var t = 0; t < vm.data.length;) {
    135165                       if (current.Id == vm.data[t].ParentResourceId) {
     166                           if (vm.data[t].IsDisposable !== undefined)
     167                               vm.clients.push(vm.data[t]);
     168                           else
     169                               vm.groups.push(vm.data[t]);
    136170                           current.children.push(vm.data.splice(t, 1)[0]);
    137171                       }
     
    145179                   return current;
    146180               }
     181
     182               $scope.toggleDisposable = function () {
     183                   $scope.calendarDispose = true;
     184                   hubber.server.toggleDisposable(vm.treeview.currentNode.Id);
     185               }
     186
    147187               function collectInfoToSave(node, refresh, last) {
    148188                   var arr = node.calendar.down[0];
     
    164204                               "" + Date.parse(arr[i].rec.end),
    165205                               arr[i].rec.days.join(",")
    166                                
     206
    167207
    168208                           ]);
     
    181221                               "" + Date.parse(arr[i].rec.end),
    182222                               arr[i].rec.days.join(",")
    183                                
     223
    184224                           ]);
    185225                       }
     
    189229               }
    190230               $scope.saveCurrentCalendar = function () {
     231                   vm.calendarSaver = true;
    191232                   collectInfoToSave(vm.treeview.currentNode, true, false);
    192233                   //true for refresh, false for showing it's only one calendar saved.
    193234               }
    194235               $scope.saveAllCalendars = function () {
     236
    195237                   $scope.allSave = [];
    196238                   for (var i = 0; i < $scope.tree.length; i++)
     
    205247                       plain: true
    206248                   }).then(function (success) {
     249                       vm.calendarSaver = true;
    207250                       for (var i = 0; i < $scope.allSave.length; i++) {
    208251                           if (i >= $scope.allSave.length - 1)
     
    255298                   $scope.currentcal = [];
    256299                   for (var i = 0; i < $scope.tree.length; i++)
    257                        removeCalendarsRecurse($scope.tree[i]);
     300                       clearCalendarsRecurse($scope.tree[i]);
    258301                   hubber.server.requestDownTime(vm.treeview.currentNode.Id);
    259302                   $(".selected.ng-binding").addClass('loaded');
    260303               }
    261                function removeCalendarsRecurse(node) {
     304               function clearCalendarsRecurse(node) {
    262305
    263306                   node.calendar = [];
     
    265308                   node.changes = false;
    266309                   for (var i = 0; i < node.children.length; i++) {
    267                        removeCalendarsRecurse(node.children[i]);
    268                    }
    269                }
    270 
     310                       clearCalendarsRecurse(node.children[i]);
     311                   }
     312               }
     313               $scope.deleteAllEvents = function () {
     314                   vm.calendarDeleter = true;
     315                   vm.selectedEventId = -1;
     316                   var node = vm.treeview.currentNode.calendar.down[0];
     317                   for (var i = 0; i < node.length;) {
     318                       if (node[i].id != '00000000-0000-0000-0000-000000000000')
     319                           vm.treeview.currentNode.todelete.push(node[i].id);
     320                       $scope.setChanged(vm.selectedEventId);
     321                       node.splice(i, 1);
     322                   }
     323                   vm.calendarDeleter = false;
     324                   ngDialog.open({
     325                       template:
     326                        '<p>All events have been deleted. Save the changes to confirm deletion, clearing will restore all the events from the server</p>',
     327                       plain: true
     328                   });
     329               }
    271330               $scope.deleteAllPreviousEvents = function () {
     331                   vm.calendarDeleter = true;
    272332                   vm.selectedEventId = -1;
    273333                   var node = vm.treeview.currentNode.calendar.down[0];
     
    282342                           i++;
    283343                   }
     344                   vm.calendarDeleter = false;
    284345                   ngDialog.open({
    285346                       template:
     
    329390                   vm.selectedEventId = vm.treeview.currentNode.calendar.down[0].length - 1;
    330391                   vm.setChanged(vm.selectedEventId);
    331                    //  $("#resourcecalendar").fullCalendar('refetchEvents');
     392                   $scope.currentcal = [];
     393                   $scope.currentcal = vm.treeview.currentNode.calendar;
     394
    332395
    333396               }
     
    342405               $scope.eventClick = function (date, jsEvent, view) {
    343406                   vm.selectedEventId = checkId(date._id);
     407               };
     408               $scope.eventClickBtn = function (id) {
     409                   vm.selectedEventId = checkId(id);
     410                   vm.goToDate();
    344411               };
    345412               /* alert on Drop */
     
    381448
    382449               };
     450               $scope.removeList = function (id) {
     451                   var index = checkId(id);
     452                   vm.selectedEventId = -1;
     453                   vm.setChanged(vm.selectedEventId);
     454                   if (vm.treeview.currentNode.calendar.down[0][index].id != "00000000-0000-0000-0000-000000000000") {
     455                       vm.treeview.currentNode.todelete.push(vm.treeview.currentNode.calendar.down[0][index].id);
     456                   }
     457                   vm.treeview.currentNode.calendar.down[0].splice(index, 1);
     458
     459
     460               };
    383461
    384462               $scope.checkDateStartEnd = function () {
    385463                   if ($scope.currentcal.down[0][vm.selectedEventId].rec.start > $scope.currentcal.down[0][vm.selectedEventId].rec.end ||
    386464                       $scope.currentcal.down[0][vm.selectedEventId].rec.end === undefined) {
    387                        
     465
    388466                       $scope.currentcal.down[0][vm.selectedEventId].rec.end = new Date($scope.currentcal.down[0][vm.selectedEventId].rec.start);
    389                        
     467
    390468                   }
    391469                   if ($scope.currentcal.down[0][vm.selectedEventId].rec.start < Date.now())
    392470                       $scope.currentcal.down[0][vm.selectedEventId].rec.start = new Date();
    393                   }
     471               }
    394472               //pushes all changes to other recurs
    395473               $scope.pushRecurChanges = function (recid) {
     
    415493                               }
    416494                               else {
    417                                    
     495
    418496                                   arr[i].start.setHours(ob.start.getHours(), ob.start.getMinutes());
    419497                                   arr[i].end.setHours(ob.end.getHours(), ob.end.getMinutes());
     
    439517                                   loop2:
    440518                                       for (var i = 0; i < arr.length; i++) {
    441                                            
     519
    442520                                           if (arr[i].rec.recid === recid) {
    443                                                var dend = (d+1000 * 3600 * 24);
     521                                               var dend = (d + 1000 * 3600 * 24);
    444522                                               if (arr[i].start.getTime() >= d &&
    445523                                                   arr[i].end.getTime() <= dend) {
     
    449527                                           }
    450528                                       }
    451  
     529
    452530                                   var ts = new Date(d);
    453531                                   ts.setHours(new Date(ob.start).getHours(), new Date(ob.start).getMinutes());
     
    465543
    466544                               }
    467                                
     545
    468546                               d += (1000 * 3600 * 24);// 1 day
    469                              
     547
    470548                           }
    471549                   });
     
    491569               }
    492570
     571               $scope.goToDate = function () {
     572                   $("#resourcecalendar").fullCalendar('gotoDate', vm.currentcal.down[0][vm.selectedEventId].start);
     573               }
    493574               /* Render Tooltip */
    494575               $scope.eventRender = function (event, element, view) {
     
    508589                       header: {
    509590                           left: 'title',
    510                            center: '',
     591                           center: 'agendaWeek, agendaDay',
    511592                           right: 'today prev,next'
    512593                       },
     
    520601
    521602
    522                    }
    523                };
    524 
    525 
    526 
     603
     604                   }
     605               };
     606
     607
     608
     609           }).filter('disp', function () {
     610               return function (input) {
     611                   return input ? 'Disposable' : 'Not disposable';
     612               }
     613           }).directive('animateOnChange', function ($timeout) {
     614               return function (scope, element, attr) {
     615                   scope.$watch(attr.animateOnChange, function (nv, ov) {
     616
     617                       if (nv != ov) {
     618                           if (scope.currentcal.down[0][scope.selectedEventId].title === "Unavailable") {
     619                               element.addClass('changed');
     620                               $timeout(function () {
     621                                   element.removeClass('changed');
     622                               }, 250); // Could be enhanced to take duration as a parameter
     623                           }
     624                           else {
     625                               element.addClass('changedshut');
     626                               $timeout(function () {
     627                                   element.removeClass('changedshut');
     628                               }, 250); // Could be enhanced to take duration as a parameter
     629                           }
     630                       }
     631                   });
     632               };
    527633           });
    528634
Note: See TracChangeset for help on using the changeset viewer.