diff --git a/SAS/DataManagement/DataManagementCommon/path.py b/SAS/DataManagement/DataManagementCommon/path.py
index 390c0ac5d24fb52fcd81ca5468b61d85700431fe..4cbf7afe6210359c5e3b2b10bc0c0225b09f9d3d 100644
--- a/SAS/DataManagement/DataManagementCommon/path.py
+++ b/SAS/DataManagement/DataManagementCommon/path.py
@@ -181,7 +181,7 @@ class PathResolver:
         dir_names = [l.split(' ')[-1].strip() for l in dir_lines]
 
         result = {'found': True, 'path': path, 'sub_directories': dir_names}
-        logger.info('getSubDirectories(%s) result: %s', path, result)
+        logger.debug('getSubDirectories(%s) result: %s', path, result)
         return result
 
     def pathExists(self, path):
diff --git a/SAS/DataManagement/StorageQueryService/cache.py b/SAS/DataManagement/StorageQueryService/cache.py
index 666ceb44deca022ac9862ac9aa76a72111a94179..2de9f88dffeff47f583f45f5a7c27acbff685ad3 100644
--- a/SAS/DataManagement/StorageQueryService/cache.py
+++ b/SAS/DataManagement/StorageQueryService/cache.py
@@ -89,16 +89,18 @@ class CacheManager:
     def _readCacheFromDisk(self):
         # maybe this cache on disk is slow, if so, revert to proper db solution
         try:
-            with open('.du_cache.py', 'r') as file:
-                with self._cacheLock:
-                    self._cache = eval(file.read())
-                if not isinstance(self._cache, dict) or 'paths' not in self._cache or 'otdb_ids' not in self._cache:
-                    self._cache = {}
+            if os.path.exists('.du_cache.py'):
+                with open('.du_cache.py', 'r') as file:
+                    with self._cacheLock:
+                        self._cache = eval(file.read().strip())
+                    if not isinstance(self._cache, dict):
+                        self._cache = {}
         except Exception as e:
             logger.error("Error while reading in du cache: %s", e)
             with self._cacheLock:
                 self._cache = {}
 
+
     def _writeCacheToDisk(self):
         try:
             with open('.du_cache.py', 'w') as file:
@@ -138,7 +140,45 @@ class CacheManager:
             if path in self._cache:
                 self._cache[path]['cache_timestamp'] = self._cache[path]['cache_timestamp'] - MAX_CACHE_ENTRY_AGE
 
+    def _scanProjectsTree(self):
+        try:
+            def addSubDirectoriesToCache(directory):
+                depth = len(directory.replace(self.disk_usage.path_resolver.projects_path, '').strip('/').split('/'))
+                if depth > 3:
+                    return
+
+                with self._cacheLock:
+                    if directory not in self._cache:
+                        logger.info('tree scan: adding \'%s\' with empty disk_usage to cache which will be du\'ed later', directory)
+                        empty_du_result = {'found': True, 'disk_usage': None, 'path': directory, 'name': directory.split('/')[-1]}
+                        self._updateCache(empty_du_result)
+
+                        if directory in self._cache:
+                            # make cache entry for directory 'old', so it will be du'ed in _updateOldEntriesInCache immediately
+                            self._cache[directory]['cache_timestamp'] -= MAX_CACHE_ENTRY_AGE
+
+                if not self._updateCacheThreadRunning:
+                    return
+
+                if depth < 3:
+                    logger.info('tree scan: scanning \'%s\'', directory)
+                    sd_result = self.disk_usage.path_resolver.getSubDirectories(directory)
+
+                    if sd_result['found']:
+                        subdir_paths = [os.path.join(directory,sd) for sd in sd_result['sub_directories']]
+
+                        for subdir_path in subdir_paths:
+                            # recurse
+                            addSubDirectoriesToCache(subdir_path)
+
+            addSubDirectoriesToCache(self.disk_usage.path_resolver.projects_path)
+            logger.info('tree scan complete')
+
+        except Exception as e:
+            logger.error(str(e))
+
     def _updateOldEntriesInCache(self):
+        logger.info('starting updating old cache entries')
         while self._updateCacheThreadRunning:
             try:
                 now = datetime.datetime.utcnow()
@@ -183,6 +223,10 @@ class CacheManager:
             except Exception as e:
                 logger.error(str(e))
 
+    def _scanProjectsTreeAndUpdateOldEntriesInCache(self):
+        self._scanProjectsTree()
+        self._updateOldEntriesInCache()
+
     def _updateProjectsDiskUsageInRADB(self):
         try:
             projects_du_result = self.getDiskUsageForPath(self.disk_usage.path_resolver.projects_path)
@@ -192,16 +236,17 @@ class CacheManager:
                 storage_resources = radbrpc.getResources(resource_types='storage', include_availability=True)
                 cep4_storage_resource = next(x for x in storage_resources if 'cep4' in x['name'])
 
-                total_capacity = cep4_storage_resource['total_capacity']
-                used_capacity = projects_du_result['disk_usage']
-                available_capacity = total_capacity - used_capacity
+                total_capacity = cep4_storage_resource.get('total_capacity')
+                used_capacity = projects_du_result.get('disk_usage')
+                if total_capacity != None and used_capacity != None:
+                    available_capacity = total_capacity - used_capacity
 
-                logger.info('updating availability capacity for %s (id=%s) to %s in the RADB',
-                            cep4_storage_resource['name'],
-                            cep4_storage_resource['id'],
-                            humanreadablesize(available_capacity))
+                    logger.info('updating availability capacity for %s (id=%s) to %s in the RADB',
+                                cep4_storage_resource['name'],
+                                cep4_storage_resource['id'],
+                                humanreadablesize(available_capacity))
 
-                radbrpc.updateResourceAvailability(cep4_storage_resource['id'], available_capacity=available_capacity)
+                    radbrpc.updateResourceAvailability(cep4_storage_resource['id'], available_capacity=available_capacity)
         except Exception as e:
             logger.error(e)
 
@@ -209,7 +254,7 @@ class CacheManager:
         self.disk_usage.open()
         self.event_bus.open()
 
-        self._updateCacheThread = Thread(target=self._updateOldEntriesInCache)
+        self._updateCacheThread = Thread(target=self._scanProjectsTreeAndUpdateOldEntriesInCache)
         self._updateCacheThread.daemon = True
         self._updateCacheThreadRunning = True
         self._updateCacheThread.start()
diff --git a/SAS/ResourceAssignment/ResourceAssignmentEditor/lib/static/app/controllers/cleanupcontroller.js b/SAS/ResourceAssignment/ResourceAssignmentEditor/lib/static/app/controllers/cleanupcontroller.js
index be1aed8cbb7c37baa9ff780f7599274d0eab7f27..45321de54451097a8ed5b6cae9d0e3178b09e605 100644
--- a/SAS/ResourceAssignment/ResourceAssignmentEditor/lib/static/app/controllers/cleanupcontroller.js
+++ b/SAS/ResourceAssignment/ResourceAssignmentEditor/lib/static/app/controllers/cleanupcontroller.js
@@ -18,14 +18,28 @@ cleanupControllerMod.controller('CleanupController', ['$scope', '$uibModal', '$h
         return defer.promise;
     };
 
-    self.deleteTaskDataWithConfirmation = function(task) {
-        dataService.getTaskDiskUsageByOTDBId(task.otdb_id).then(function(du_result) {
-            if(du_result.found) {
-                openDeleteConfirmationDialog(task, du_result);
-            } else {
-                alert(du_result.message);
-            }
-        });
+    self.deleteSelectedTasksDataWithConfirmation = function() {
+        var tasks = dataService.selected_task_ids.map(function(t_id) { return dataService.taskDict[t_id]; });
+        self.deleteTasksDataWithConfirmation(tasks);
+    }
+
+    self.deleteTasksDataWithConfirmation = function(tasks) {
+        du_results = [];
+        for(var task of tasks) {
+            dataService.getTaskDiskUsage(task).then(function(du_result) {
+                if(du_result.found) {
+                    du_results.push(du_result);
+
+                    if(du_results.length == tasks.length) {
+                        openDeleteConfirmationDialog(du_results);
+                    }
+
+                    console.log(du_results);
+                } else {
+                    alert(du_result.message);
+                }
+            });
+        }
     };
 
     function deleteTaskData(task, delete_is, delete_cs, delete_uv, delete_im, delete_img, delete_pulp, delete_scratch) {
@@ -37,17 +51,16 @@ cleanupControllerMod.controller('CleanupController', ['$scope', '$uibModal', '$h
         });
     };
 
-    function openDeleteConfirmationDialog(task, du_result) {
-        var path = du_result.task_directory.path;
-
+    function openDeleteConfirmationDialog(du_results) {
         var modalInstance = $uibModal.open({
             animation: false,
             template: '<div class="modal-header">\
                             <h3 class="modal-title">Are you sure?</h3>\
                         </div>\
                         <div class="modal-body">\
-                            <p>This will delete all selected data in ' + path + '<br>\
-                            Are you sure?</p>\
+                            <p>This will delete all selected data in: \
+                            <ul><li ng-repeat="path in paths">{{path}}</li></ul>\
+                            <br>Are you sure?</p>\
                             <label ng-if="has_is" style="margin-left:24px">IS: {{amount_is}}<input style="margin-left:8px" type="checkbox" ng-model="$parent.delete_is"></label>\
                             <label ng-if="has_cs" style="margin-left:24px">CS: {{amount_cs}}<input style="margin-left:8px" type="checkbox" ng-model="$parent.delete_cs"></label>\
                             <label ng-if="has_uv" style="margin-left:24px">UV: {{amount_uv}}<input style="margin-left:8px" type="checkbox" ng-model="$parent.delete_uv"></label>\
@@ -61,19 +74,53 @@ cleanupControllerMod.controller('CleanupController', ['$scope', '$uibModal', '$h
                             <button class="btn btn-warning" type="button" autofocus ng-click="cancel()">Cancel</button>\
                         </div>',
             controller: function ($scope, $uibModalInstance) {
-                $scope.has_is = du_result.sub_directories.hasOwnProperty(path + '/is');
-                $scope.has_cs = du_result.sub_directories.hasOwnProperty(path + '/cs');
-                $scope.has_uv = du_result.sub_directories.hasOwnProperty(path + '/uv');
-                $scope.has_im = du_result.sub_directories.hasOwnProperty(path + '/im');
-                $scope.has_img = du_result.sub_directories.hasOwnProperty(path + '/img');
-                $scope.has_pulp = du_result.sub_directories.hasOwnProperty(path + '/pulp');
-                $scope.has_scratch = du_result.task_directory.hasOwnProperty('scratch_paths');;
-                $scope.amount_is = $scope.has_is ? du_result.sub_directories[path + '/is'].disk_usage_readable : '';
-                $scope.amount_cs = $scope.has_cs ? du_result.sub_directories[path + '/cs'].disk_usage_readable : '';
-                $scope.amount_uv = $scope.has_uv ? du_result.sub_directories[path + '/uv'].disk_usage_readable : '';
-                $scope.amount_im = $scope.has_im ? du_result.sub_directories[path + '/im'].disk_usage_readable : '';
-                $scope.amount_img = $scope.has_img ? du_result.sub_directories[path + '/img'].disk_usage_readable : '';
-                $scope.amount_pulp = $scope.has_pulp ? du_result.sub_directories[path + '/pulp'].disk_usage_readable : '';
+                $scope.paths = du_results.map(function(r) { return r.task_directory.path; });
+                $scope.has_is = false;
+                $scope.has_cs = false;
+                $scope.has_uv = false;
+                $scope.has_im = false;
+                $scope.has_img = false;
+                $scope.has_pulp = false;
+                $scope.has_scratch = false;
+                $scope.amount_is = 0;
+                $scope.amount_cs = 0;
+                $scope.amount_uv = 0;
+                $scope.amount_im = 0;
+                $scope.amount_img = 0;
+                $scope.amount_pulp = 0;
+
+                for(var du_result of du_results) {
+                    var path = du_result.task_directory.path;
+                    var has_is = du_result.sub_directories.hasOwnProperty(path + '/is');
+                    var has_cs = du_result.sub_directories.hasOwnProperty(path + '/cs');
+                    var has_uv = du_result.sub_directories.hasOwnProperty(path + '/uv');
+                    var has_im = du_result.sub_directories.hasOwnProperty(path + '/im');
+                    var has_img = du_result.sub_directories.hasOwnProperty(path + '/img');
+                    var has_pulp = du_result.sub_directories.hasOwnProperty(path + '/pulp');
+                    var has_scratch = du_result.sub_directories.hasOwnProperty('scratch_paths');
+
+                    $scope.has_is |= has_is;
+                    $scope.has_cs |= has_cs;
+                    $scope.has_uv |= has_uv;
+                    $scope.has_im |= has_im;
+                    $scope.has_img |= has_img;
+                    $scope.has_pulp |= has_pulp;
+                    $scope.has_scratch |= has_scratch;
+
+                    $scope.amount_is += has_is ? du_result.sub_directories[path + '/is'].disk_usage : 0;
+                    $scope.amount_cs += has_cs ? du_result.sub_directories[path + '/cs'].disk_usage : 0;
+                    $scope.amount_uv += has_uv ? du_result.sub_directories[path + '/uv'].disk_usage : 0;
+                    $scope.amount_im += has_im ? du_result.sub_directories[path + '/im'].disk_usage : 0;
+                    $scope.amount_img += has_img ? du_result.sub_directories[path + '/img'].disk_usage : 0;
+                    $scope.amount_pulp += has_pulp ? du_result.sub_directories[path + '/pulp'].disk_usage : 0;
+                }
+
+                $scope.amount_is = dataService.humanreadablesize($scope.amount_is);
+                $scope.amount_cs = dataService.humanreadablesize($scope.amount_cs);
+                $scope.amount_uv = dataService.humanreadablesize($scope.amount_uv);
+                $scope.amount_im = dataService.humanreadablesize($scope.amount_im);
+                $scope.amount_img = dataService.humanreadablesize($scope.amount_img);
+                $scope.amount_pulp = dataService.humanreadablesize($scope.amount_pulp);
 
                 $scope.delete_is = true;
                 $scope.delete_cs = true;
@@ -85,7 +132,10 @@ cleanupControllerMod.controller('CleanupController', ['$scope', '$uibModal', '$h
 
                 $scope.ok = function () {
                     $uibModalInstance.close();
-                    deleteTaskData(task, $scope.delete_is, $scope.delete_cs, $scope.delete_uv, $scope.delete_im, $scope.delete_img, $scope.delete_pulp, $scope.delete_scratch);
+                    for(var du_result of du_results) {
+                        var task = du_result.task;
+                        deleteTaskData(task, $scope.delete_is, $scope.delete_cs, $scope.delete_uv, $scope.delete_im, $scope.delete_img, $scope.delete_pulp, $scope.delete_scratch);
+                    }
                 };
 
                 $scope.cancel = function () {
@@ -95,6 +145,9 @@ cleanupControllerMod.controller('CleanupController', ['$scope', '$uibModal', '$h
         });
     };
 
+    self.showAllProjectsDiskUsage = function() {
+        self.showTaskDiskUsage(undefined);
+    }
 
     self.showTaskDiskUsage = function(task) {
         var modalInstance = $uibModal.open({
@@ -103,6 +156,8 @@ cleanupControllerMod.controller('CleanupController', ['$scope', '$uibModal', '$h
                             <h3 class="modal-title">Disk usage</h3>\
                         </div>\
                         <div class="modal-body" style="text-align:right">\
+                            <highchart id="chart_total_disk_usage" config="totalDiskUsageChartConfig" style="width: 960px; height: 120px; margin-bottom: 20px;" ></highchart>\
+                            <hr>\
                             <highchart id="chart_disk_usage" config="diskUsageChartConfig" style="width: 960px; height: 720px;" ></highchart>\
                             <p>\
                               <span style="margin-right:50px">Last updated at: {{leastRecentCacheTimestamp | date }}</span>\
@@ -154,6 +209,9 @@ cleanupControllerMod.controller('CleanupController', ['$scope', '$uibModal', '$h
                             type: 'pie',
                             animation: {
                                 duration: 200
+                            },
+                            legend: {
+                                enabled: false
                             }
                         },
                         legend: {
@@ -191,6 +249,70 @@ cleanupControllerMod.controller('CleanupController', ['$scope', '$uibModal', '$h
                     loading: false
                 }
 
+                $scope.totalDiskUsageChartSeries = [];
+
+                var cep4storage_resource = dataService.resources.find(function(r) { return r.name == 'cep4storage'; });
+                if(cep4storage_resource) {
+                    $scope.totalDiskUsageChartSeries = [{name:'Free', data:[100.0*cep4storage_resource.available_capacity/cep4storage_resource.total_capacity], color:'#a3f75c'},
+                                                        {name:'Used', data:[100.0*cep4storage_resource.used_capacity/cep4storage_resource.total_capacity], color:'#f45b5b'}];
+                }
+
+                $scope.totalDiskUsageChartConfig = {
+                    options: {
+                        chart: {
+                            type: 'bar',
+                            animation: {
+                                duration: 200
+                            },
+                            legend: {
+                                enabled: false
+                            }
+                        },
+                        navigation: {
+                            buttonOptions: {
+                                enabled: false
+                            }
+
+                        },
+                        plotOptions: {
+                            bar: {
+                                allowPointSelect: false,
+                                cursor: 'pointer',
+                                dataLabels: {
+                                    enabled: false
+                                },
+                                showInLegend: false,
+                            },
+                            series: {
+                                stacking: 'normal',
+                                pointWidth: 32
+                            },
+                        },
+                        yAxis: {
+                            visible: true,
+                            title: {text:'Percentage'},
+                            min: 0,
+                            max: 100,
+                            endOnTick: false
+                        },
+                        xAxis: {
+                            visible: false
+                        },
+                        tooltip: {
+                            headerFormat: '{series.name}<br/>',
+                            pointFormat: '{point.name}: <b>{point.percentage:.1f}%</b>'
+                        },
+                    },
+                    series: $scope.totalDiskUsageChartSeries,
+                    title: {
+                        text: 'CEP4 total disk usage'
+                    },
+                    credits: {
+                        enabled: false
+                    },
+                    loading: false
+                }
+
                 var loadTaskDiskUsage = function(otdb_id) {
                     dataService.getTaskDiskUsageByOTDBId(otdb_id).then(function(result) {
                         if(result.found) {
@@ -206,7 +328,7 @@ cleanupControllerMod.controller('CleanupController', ['$scope', '$uibModal', '$h
                             sub_directory_names.sort(function(a, b) { return ((a.name < b.name) ? -1 : ((a.name > b.name) ? 1 : 0)); });
                             for(var sub_dir of sub_directory_names) {
                                 var sub_dir_result = result.sub_directories[sub_dir];
-                                $scope.diskUsageChartSeries[0].data.push({name:sub_dir_result.name + ' ' + sub_dir_result.disk_usage_readable,y:sub_dir_result.disk_usage});
+                                $scope.diskUsageChartSeries[0].data.push({name:sub_dir_result.name + ' ' + sub_dir_result.disk_usage_readable,y:sub_dir_result.disk_usage || 0});
 
                                 if(sub_dir_result.cache_timestamp < $scope.leastRecentCacheTimestamp) {
                                     $scope.leastRecentCacheTimestamp = sub_dir_result.cache_timestamp;
@@ -215,6 +337,7 @@ cleanupControllerMod.controller('CleanupController', ['$scope', '$uibModal', '$h
                             $scope.leastRecentCacheTimestamp = dataService.convertDatestringToLocalUTCDate($scope.leastRecentCacheTimestamp);
                         }else {
                             $scope.ok();
+                            $scope.$evalAsync(function() { alert("Could not find disk usage for task " + otdb_id); });
                         }
                     });
                 };
@@ -233,7 +356,7 @@ cleanupControllerMod.controller('CleanupController', ['$scope', '$uibModal', '$h
                             for(var sub_dir of sub_directory_names) {
                                 var sub_dir_result = result.sub_directories[sub_dir];
                                 $scope.diskUsageChartSeries[0].data.push({name:sub_dir_result.name + ' ' + sub_dir_result.disk_usage_readable,
-                                                                        y:sub_dir_result.disk_usage,
+                                                                        y:sub_dir_result.disk_usage || 0,
                                                                         otdb_id: parseInt(sub_dir_result.name.slice(1)) });
 
                                 if(sub_dir_result.cache_timestamp < $scope.leastRecentCacheTimestamp) {
@@ -243,6 +366,7 @@ cleanupControllerMod.controller('CleanupController', ['$scope', '$uibModal', '$h
                             $scope.leastRecentCacheTimestamp = dataService.convertDatestringToLocalUTCDate($scope.leastRecentCacheTimestamp);
                         }else {
                             $scope.ok();
+                            $scope.$evalAsync(function() { alert("Could not find disk usage for project " + project_name); });
                         }
                     });
                 };
@@ -261,7 +385,7 @@ cleanupControllerMod.controller('CleanupController', ['$scope', '$uibModal', '$h
                             for(var sub_dir of sub_directory_names) {
                                 var sub_dir_result = result.sub_directories[sub_dir];
                                 $scope.diskUsageChartSeries[0].data.push({name:sub_dir_result.name + ' ' + sub_dir_result.disk_usage_readable,
-                                                                        y:sub_dir_result.disk_usage,
+                                                                        y:sub_dir_result.disk_usage || 0,
                                                                         project_name: sub_dir_result.name });
 
                                 if(sub_dir_result.cache_timestamp < $scope.leastRecentCacheTimestamp) {
@@ -271,11 +395,16 @@ cleanupControllerMod.controller('CleanupController', ['$scope', '$uibModal', '$h
                             $scope.leastRecentCacheTimestamp = dataService.convertDatestringToLocalUTCDate($scope.leastRecentCacheTimestamp);
                         }else {
                             $scope.ok();
+                            $scope.$evalAsync(function() { alert("Could not find disk usage for all projects"); });
                         }
                     });
                 };
 
-                loadTaskDiskUsage(task.otdb_id);
+                if(task) {
+                    loadTaskDiskUsage(task.otdb_id);
+                } else {
+                    loadAllProjectsDiskUsage();
+                }
             }
         });
     };
diff --git a/SAS/ResourceAssignment/ResourceAssignmentEditor/lib/static/app/controllers/datacontroller.js b/SAS/ResourceAssignment/ResourceAssignmentEditor/lib/static/app/controllers/datacontroller.js
index a2e911f744f381c81d57f04943db12fac368dff8..e9af7da1c89ff7b4625d8f7b020abab012b3b894 100644
--- a/SAS/ResourceAssignment/ResourceAssignmentEditor/lib/static/app/controllers/datacontroller.js
+++ b/SAS/ResourceAssignment/ResourceAssignmentEditor/lib/static/app/controllers/datacontroller.js
@@ -33,7 +33,7 @@ angular.module('raeApp').factory("dataService", ['$http', '$q', function($http,
 
     self.selected_resource_id;
     self.selected_resourceGroup_id;
-    self.selected_task_id;
+    self.selected_task_ids = [];
     self.selected_project_id;
     self.selected_resourceClaim_id;
 
@@ -48,6 +48,48 @@ angular.module('raeApp').factory("dataService", ['$http', '$q', function($http,
     self.viewTimeSpan = {from: new Date(), to: new Date() };
     self.autoFollowNow = true;
 
+
+    self.humanreadablesize = function(num) {
+        var units = ['', 'K', 'M', 'G', 'T', 'P', 'E', 'Z'];
+        for(unit of units) {
+            if(Math.abs(num) < 1000.0) {
+                return num.toPrecision(4).toString() + unit;
+            }
+            num /= 1000.0;
+        }
+        return num.toPrecision(5).toString() + 'Y';
+    }
+
+    self.isTaskIdSelected = function(task_id) {
+        return self.selected_task_ids.indexOf(task_id) != -1;
+    }
+
+    self.toggleTaskSelection = function(task_id) {
+        if(self.isTaskIdSelected(task_id)) {
+            self.removeSelectedTaskId(task_id);
+        } else {
+            self.addSelectedTaskId(task_id);
+        }
+    }
+
+    self.addSelectedTaskId = function(task_id) {
+        if(self.selected_task_ids.indexOf(task_id) == -1) {
+            self.selected_task_ids.push(task_id);
+        }
+    }
+
+    self.removeSelectedTaskId = function(task_id) {
+        var idx = self.selected_task_ids.indexOf(task_id);
+        if(idx != -1) {
+            self.selected_task_ids.splice(idx, 1);
+        }
+    }
+
+    self.setSelectedTaskId = function(task_id) {
+        self.selected_task_ids.splice(0, self.selected_task_ids.length);
+        self.selected_task_ids.push(task_id);
+    }
+
     self.floorDate = function(date, hourMod=1, minMod=1) {
         var min = date.getMinutes();
         min = date.getMinutes()/minMod;
@@ -246,25 +288,27 @@ angular.module('raeApp').factory("dataService", ['$http', '$q', function($http,
 
             if(initialTaskLoad && self.tasks.length > 0) {
                 setTimeout(function() {
+                    self.selected_task_ids.splice(0,self.selected_task_ids.length);
+
                     //try to select current task
                     var currentTasks = self.tasks.filter(function(t) { return t.starttime <= self.lofarTime && t.endtime >= self.lofarTime; });
 
                     if(currentTasks.length > 0) {
-                        self.selected_task_id = currentTasks[0].id;
+                        self.selected_task_ids.push(currentTasks[0].id);
                     } else {
                         //try to select next task
                         var nextTasks = self.tasks.filter(function(t) { return t.starttime >= self.lofarTime; }).sort();
 
                         if(nextTasks.length > 0) {
-                            self.selected_task_id = nextTasks[0].id;
+                            self.selected_task_ids.push(nextTasks[0].id);
                         } else {
                             //try to select most recent task
                             var prevTasks = self.tasks.filter(function(t) { return t.endtime <= self.lofarTime; }).sort();
 
                             if(prevTasks.length > 0) {
-                                self.selected_task_id = prevTasks[prevTasks.length-1].id;
+                                self.selected_task_ids.push(prevTasks[prevTasks.length-1].id);
                             } else {
-                                self.selected_task_id = self.tasks[0].id;
+                                self.selected_task_ids.push(self.tasks[0].id);
                             }
                         }
                     }
@@ -296,7 +340,18 @@ angular.module('raeApp').factory("dataService", ['$http', '$q', function($http,
     self.getTaskDiskUsageByOTDBId = function(otdb_id) {
         var defer = $q.defer();
         $http.get('/rest/tasks/otdb/' + otdb_id + '/diskusage').success(function(result) {
-            console.log(result);
+            defer.resolve(result);
+        }).error(function(result) {
+            defer.resolve({found:false});
+        });
+
+        return defer.promise;
+    };
+
+    self.getTaskDiskUsage = function(task) {
+        var defer = $q.defer();
+        $http.get('/rest/tasks/otdb/' + task.otdb_id + '/diskusage').success(function(result) {
+            result.task = task;
             defer.resolve(result);
         }).error(function(result) {
             defer.resolve({found:false});
@@ -730,24 +785,27 @@ dataControllerMod.controller('DataController',
     $scope.selectCurrentTask = function() {
         var currentTasks = dataService.tasks.filter(function(t) { return t.starttime <= dataService.viewTimeSpan.to && t.endime >= dataService.viewTimeSpan.from; });
         if(currentTasks.lenght > 0) {
-            dataService.selected_task_id = currentTasks[0].id;
+            dataService.setSelectedTaskId(currentTasks[0].id);
         }
     };
 
     $scope.jumpToSelectedTask = function() {
-        if(dataService.selected_task_id == undefined)
+        if(dataService.selected_task_ids == undefined)
             return;
 
-        var task = dataService.taskDict[dataService.selected_task_id];
+        var tasks = dataService.selected_task_ids.map(function(t_id) { return dataService.taskDict[t_id]; });
 
-        if(task == undefined)
+        if(tasks.lenght == 0)
             return;
 
-        var taskDurationInmsec = task.endtime.getTime() - task.starttime.getTime();
-        var taskDurationInMinutes = taskDurationInmsec/60000;
-        var viewSpanInMinutes = taskDurationInMinutes;
+        var minStarttime = new Date(Math.min.apply(null, tasks.map(function(t) { return t.starttime; })));
+        var maxEndtime = new Date(Math.max.apply(null, tasks.map(function(t) { return t.endtime; })));
 
-        var fittingSpans = $scope.zoomTimespans.filter(function(w) { return w.value >= taskDurationInMinutes; });
+        var selectedTasksDurationInmsec = maxEndtime.getTime() - minStarttime.getTime();
+        var selectedTasksDurationInMinutes = selectedTasksDurationInmsec/60000;
+        var viewSpanInMinutes = selectedTasksDurationInMinutes;
+
+        var fittingSpans = $scope.zoomTimespans.filter(function(w) { return w.value >= selectedTasksDurationInMinutes; });
         if(fittingSpans.length > 0) {
             $scope.zoomTimespan = fittingSpans[0];
             //select one span larger if possible
@@ -756,7 +814,7 @@ dataControllerMod.controller('DataController',
             viewSpanInMinutes = $scope.zoomTimespan.value;
         }
 
-        var focusTime = new Date(task.starttime.getTime() + 0.5*taskDurationInmsec);
+        var focusTime = new Date(minStarttime.getTime() + 0.5*selectedTasksDurationInmsec);
 
         dataService.viewTimeSpan = {
             from: dataService.floorDate(new Date(focusTime.getTime() - 0.4*viewSpanInMinutes*60*1000), 1, 5),
@@ -788,11 +846,14 @@ dataControllerMod.controller('DataController',
 
         if(dataService.autoFollowNow) {
             focusTime = dataService.floorDate(dataService.lofarTime, 1, 5);
-        } else if(dataService.selected_task_id != undefined) {
-            var task = dataService.taskDict[dataService.selected_task_id];
+        } else {
+            var tasks = dataService.selected_task_ids.map(function(t_id) { return dataService.taskDict[t_id]; });
+
+            if(tasks.lenght > 0) {
+                var minStarttime = new Date(Math.min.apply(null, tasks.map(function(t) { return t.starttime; })));
+                var maxEndtime = new Date(Math.max.apply(null, tasks.map(function(t) { return t.endtime; })));
 
-            if(task) {
-                focusTime = dataService.floorDate(task.starttime, 1, 5);
+                focusTime = dataService.floorDate(new Date(0.5*(minStarttime.getTime() + maxEndtime.getTime())), 1, 5);
             }
         }
 
diff --git a/SAS/ResourceAssignment/ResourceAssignmentEditor/lib/static/app/controllers/ganttprojectcontroller.js b/SAS/ResourceAssignment/ResourceAssignmentEditor/lib/static/app/controllers/ganttprojectcontroller.js
index 87f6ced5d7b99e3425b14c264dcaaff12083682b..09fd23f3e00d779e9a9082b73effb464b49ee871 100644
--- a/SAS/ResourceAssignment/ResourceAssignmentEditor/lib/static/app/controllers/ganttprojectcontroller.js
+++ b/SAS/ResourceAssignment/ResourceAssignmentEditor/lib/static/app/controllers/ganttprojectcontroller.js
@@ -59,53 +59,19 @@ ganttProjectControllerMod.controller('GanttProjectController', ['$scope', 'dataS
                 } else if (directiveName === 'ganttTask') {
                     directiveElement.bind('click', function(event) {
                         if(directiveScope.task.model.raTask) {
-                            $scope.dataService.selected_task_id = directiveScope.task.model.raTask.id;
+                            if(event.ctrlKey) {
+                                $scope.dataService.toggleTaskSelection(directiveScope.task.model.raTask.id);
+                            } else {
+                                $scope.dataService.setSelectedTaskId(directiveScope.task.model.raTask.id);
+                            }
                         }
                     });
                     directiveElement.bind('dblclick', function(event) {
                         if(directiveScope.task.model.raTask) {
-                            $scope.dataService.selected_task_id = directiveScope.task.model.raTask.id;
+                            $scope.dataService.setSelectedTaskId(directiveScope.task.model.raTask.id);
                             $scope.jumpToSelectedTask();
                         }
                     });
-//                     directiveElement.bind('contextmenu', function(event) {
-//                         if(directiveScope.task.model.raTask) {
-//                             $scope.dataService.selected_task_id = directiveScope.task.model.raTask.id;
-//                         }
-//
-//                         //search for already existing contextmenu element
-//                         if(directiveElement.find('#gantt-project-context-menu').length) {
-//                             //found, remove it, so we can create a fresh one
-//                             directiveElement.find('#gantt-project-context-menu')[0].remove();
-//                         }
-//
-//                         //create contextmenu element
-//                         //with list of menu items,
-//                         //each with it's own action
-//                         var contextmenuElement = angular.element('<div id="gantt-project-context-menu"></div>');
-//                         ulElement = angular.element('<ul style="z-index:10000; position:fixed; top:initial; left:initial; display:block;" role="menu" class="dropdown-menu"></ul>');
-//                         contextmenuElement.append(ulElement);
-//                         liElement = angular.element('<li><a href="#">Copy Task</a></li>');
-//                         ulElement.append(liElement);
-//                         liElement.on('click', function() {
-//                             $scope.dataService.copyTask(directiveScope.task.model.raTask);
-//                             closeContextMenu();
-//                         });
-//
-//                         var closeContextMenu = function() {
-//                             contextmenuElement.remove();
-//                             angular.element(document).unbind('click', closeContextMenu);
-//                         };
-//
-//                         //click anywhere to remove the contextmenu
-//                         angular.element(document).bind('click', closeContextMenu);
-//
-//                         //add contextmenu to clicked element
-//                         directiveElement.append(contextmenuElement);
-//
-//                         //prevent bubbling event upwards
-//                         return false;
-//                     });
                 }
             });
 
@@ -115,7 +81,6 @@ ganttProjectControllerMod.controller('GanttProjectController', ['$scope', 'dataS
                 }
                 if (directiveName === 'ganttTask') {
                     directiveElement.unbind('dblclick');
-//                     directiveElement.unbind('contextmenu');
                 }
             });
         }
@@ -238,7 +203,7 @@ ganttProjectControllerMod.controller('GanttProjectController', ['$scope', 'dataS
                             movable: $.inArray(task.status_id, editableTaskStatusIds) > -1
                         };
 
-                        if(task.id == dataService.selected_task_id) {
+                        if(dataService.isTaskIdSelected(task.id)) {
                             rowTask.classes += ' task-selected-task';
                         }
 
@@ -265,7 +230,7 @@ ganttProjectControllerMod.controller('GanttProjectController', ['$scope', 'dataS
     };
 
     $scope.$watch('dataService.initialLoadComplete', function() { $scope.$evalAsync(updateGanttData); });
-    $scope.$watch('dataService.selected_task_id', function() { $scope.$evalAsync(updateGanttData); });
+    $scope.$watch('dataService.selected_task_ids', function() { $scope.$evalAsync(updateGanttData); }, true);
     $scope.$watch('dataService.viewTimeSpan', function() { $scope.$evalAsync(updateGanttData); }, true);
     $scope.$watch('dataService.filteredTaskChangeCntr', function() { $scope.$evalAsync(updateGanttData); });
     $scope.$watch('dataService.lofarTime', function() {
diff --git a/SAS/ResourceAssignment/ResourceAssignmentEditor/lib/static/app/controllers/ganttresourcecontroller.js b/SAS/ResourceAssignment/ResourceAssignmentEditor/lib/static/app/controllers/ganttresourcecontroller.js
index 9ec685de16ea6e07b287373f288b284197c50370..4ce9888a4e68bb635d9a5b06dea50d9acccc1efb 100644
--- a/SAS/ResourceAssignment/ResourceAssignmentEditor/lib/static/app/controllers/ganttresourcecontroller.js
+++ b/SAS/ResourceAssignment/ResourceAssignmentEditor/lib/static/app/controllers/ganttresourcecontroller.js
@@ -58,17 +58,17 @@ ganttResourceControllerMod.controller('GanttResourceController', ['$scope', 'dat
                 } else if (directiveName === 'ganttTask') {
                     directiveElement.bind('click', function(event) {
                         if(directiveScope.task.model.raTask) {
-                            $scope.dataService.selected_task_id = directiveScope.task.model.raTask.id;
+                            if(event.ctrlKey) {
+                                $scope.dataService.toggleTaskSelection(directiveScope.task.model.raTask.id);
+                            } else {
+                                $scope.dataService.setSelectedTaskId(directiveScope.task.model.raTask.id);
+                            }
                         }
                         if(directiveScope.task.model.claim) {
                             $scope.dataService.selected_resourceClaim_id = directiveScope.task.model.claim.id;
                         }
                     });
                     directiveElement.bind('contextmenu', function(event) {
-                        if(directiveScope.task.model.raTask) {
-                            $scope.dataService.selected_task_id = directiveScope.task.model.raTask.id;
-                        }
-
                         //search for already existing contextmenu element
                         if(directiveElement.find('#gantt-resource-context-menu').length) {
                             //found, remove it, so we can create a fresh one
@@ -335,10 +335,9 @@ ganttResourceControllerMod.controller('GanttResourceController', ['$scope', 'dat
                         movable: $.inArray(task.status_id, editableTaskStatusIds) > -1
                     };
 
-
                     if(claim.id == dataService.selected_resourceClaim_id) {
                         claimTask.classes += ' claim-selected-claim';
-                    } else if(task.id == dataService.selected_task_id) {
+                    } else if(dataService.isTaskIdSelected(task.id)) {
                         claimTask.classes += ' claim-selected-task';
                     }
 
@@ -427,7 +426,7 @@ ganttResourceControllerMod.controller('GanttResourceController', ['$scope', 'dat
                                     movable: $.inArray(task.status_id, editableTaskStatusIds) > -1
                                 };
 
-                                if(task.id == dataService.selected_task_id) {
+                                if(dataService.isTaskIdSelected(task.id)) {
                                     claimTask.classes += ' claim-selected-task';
                                 }
 
@@ -469,7 +468,7 @@ ganttResourceControllerMod.controller('GanttResourceController', ['$scope', 'dat
     };
 
     $scope.$watch('dataService.initialLoadComplete', function() { $scope.$evalAsync(updateGanttData); });
-    $scope.$watch('dataService.selected_task_id', function() { $scope.$evalAsync(updateGanttData); });
+    $scope.$watch('dataService.selected_task_ids', function() { $scope.$evalAsync(updateGanttData); }, true);
     $scope.$watch('dataService.viewTimeSpan', function() { $scope.$evalAsync(updateGanttData); }, true);
     $scope.$watch('dataService.claimChangeCntr', function() { $scope.$evalAsync(updateGanttData); });
     $scope.$watch('dataService.filteredTaskChangeCntr', function() { $scope.$evalAsync(updateGanttData); });
diff --git a/SAS/ResourceAssignment/ResourceAssignmentEditor/lib/static/app/controllers/gridcontroller.js b/SAS/ResourceAssignment/ResourceAssignmentEditor/lib/static/app/controllers/gridcontroller.js
index 6f13c5ac69bbe04355d96c1fecf6a187bfec0cd8..e64b3574dbb522c36d889ccc511a9e2e69c97134 100644
--- a/SAS/ResourceAssignment/ResourceAssignmentEditor/lib/static/app/controllers/gridcontroller.js
+++ b/SAS/ResourceAssignment/ResourceAssignmentEditor/lib/static/app/controllers/gridcontroller.js
@@ -113,8 +113,9 @@ $scope.columns = [
         enableRowSelection: true,
         enableRowHeaderSelection: true,
         enableFullRowSelection: false,
+        modifierKeysToMultiSelect: true,
+        multiSelect:true,
         enableSelectionBatchEvent:false,
-        multiSelect:false,
         gridMenuShowHideColumns: false,
         columnDefs: $scope.columns,
         data: [],
@@ -135,10 +136,13 @@ $scope.columns = [
                         var row = rows[i];
                         if(row.visible)
                         {
-                            var task = taskDict[row.entity.id];
+                            var task_id = row.entity.id;
+                            var task = taskDict[task_id];
                             if(task) {
                                 $scope.dataService.filteredTasks.push(task);
                             }
+
+                            row.setSelected($scope.dataService.selected_task_ids.indexOf(task_id) != -1);
                         }
                     }
 
@@ -154,8 +158,12 @@ $scope.columns = [
             });
 
             gridApi.selection.on.rowSelectionChanged($scope,function(row){
-                if(row.entity.id && row.isSelected) {
-                    $scope.dataService.selected_task_id = row.entity.id;
+                if(row.entity.id) {
+                    if(row.isSelected) {
+                        $scope.dataService.addSelectedTaskId(row.entity.id);
+                    } else if(!row.isSelected) {
+                        $scope.dataService.removeSelectedTaskId(row.entity.id);
+                    }
                 }
             });
         }
@@ -221,19 +229,30 @@ $scope.columns = [
         $scope.$evalAsync(fillGroupsColumFilterSelectOptions);
     };
 
-    function jumpToSelectedTaskRow() {
-        var taskIdx = $scope.gridOptions.data.findIndex(function(row) {return row.id == dataService.selected_task_id});
+    function jumpToSelectedTaskRows() {
+        var rowIndices = dataService.selected_task_ids.map(function(t_id) { return $scope.gridOptions.data.findIndex(function(row) {return row.id == t_id; } ); });
+        rowIndices = rowIndices.filter(function(idx) {return idx > -1;}).sort();
+
+        for(var rowIndex of rowIndices) {
+            $scope.gridApi.core.scrollTo($scope.gridOptions.data[rowIndex], null);
+        }
+    };
+
+    function onSelectedTaskIdsChanged() {
+        var selected_task_ids = $scope.dataService.selected_task_ids;
+        var rows = $scope.gridApi.grid.rows;
 
-        if(taskIdx > -1) {
-            $scope.gridApi.selection.selectRow($scope.gridOptions.data[taskIdx]);
-            $scope.gridApi.core.scrollTo($scope.gridOptions.data[taskIdx], null);
+        for(var row of rows) {
+            row.setSelected(selected_task_ids.indexOf(row.entity.id) != -1);
         }
+
+        $scope.$evalAsync(jumpToSelectedTaskRows);
     };
 
     $scope.$watch('dataService.taskChangeCntr', function() { $scope.$evalAsync(populateList); });
     $scope.$watch('dataService.viewTimeSpan', function() {
         $scope.$evalAsync(populateList);
-        $scope.$evalAsync(jumpToSelectedTaskRow);
+        $scope.$evalAsync(jumpToSelectedTaskRows);
     }, true);
 
     $scope.$watch('dataService.initialLoadComplete', function() {
@@ -281,7 +300,7 @@ $scope.columns = [
         fillColumFilterSelectOptions(groupSelectOptions, $scope.columns[7]);
     };
 
-    $scope.$watch('dataService.selected_task_id', jumpToSelectedTaskRow);}
+    $scope.$watch('dataService.selected_task_ids', onSelectedTaskIdsChanged, true);}
 ]);
 
 gridControllerMod.directive('contextMenu', ['$document', '$window', function($document, $window) {
@@ -301,7 +320,12 @@ gridControllerMod.directive('contextMenu', ['$document', '$window', function($do
 
             var taskId = rowEntity.id;
             var task = dataService.taskDict[taskId];
-            dataService.selected_task_id = taskId;
+            if(!task)
+                return true;
+
+            if(!dataService.isTaskIdSelected(taskId)) {
+                dataService.setSelectedTaskId(taskId);
+            }
 
             var docElement = angular.element($document);
 
@@ -322,35 +346,36 @@ gridControllerMod.directive('contextMenu', ['$document', '$window', function($do
             var ulElement = angular.element('<ul class="dropdown-menu" role="menu" style="left:' + event.clientX + 'px; top:' + event.clientY + 'px; z-index: 100000; display:block;"></ul>');
             contextmenuElement.append(ulElement);
 
-//             var liElement = angular.element('<li><a href="#">Copy Task</a></li>');
-//             ulElement.append(liElement);
-//             liElement.on('click', function() {
-//                 closeContextMenu();
-//                 dataService.copyTask(task);
-//             });
-
             if(task.type == 'observation' && dataService.config.inspection_plots_base_url) {
                 var liElement = angular.element('<li><a href="#">Inspection Plots</a></li>');
                 ulElement.append(liElement);
                 liElement.on('click', function() {
                     closeContextMenu();
-                    var url = dataService.config.inspection_plots_base_url + '/' + task.otdb_id;
-                    $window.open(url, '_blank');
+                    var tasks = dataService.selected_task_ids.map(function(t_id) { return dataService.taskDict[t_id]; });
+                    for(var t of tasks) {
+                        if(t) {
+                            var url = dataService.config.inspection_plots_base_url + '/' + t.otdb_id;
+                            $window.open(url, '_blank');
+                        }
+                    }
                 });
             }
 
-            var liElement = angular.element('<li><a href="#">Show disk usage</a></li>');
+            var liContent = dataService.selected_task_ids.length == 1 ? '<li><a href="#">Show disk usage</a></li>' : '<li><a href="#" style="color:#aaaaaa">Show disk usage</a></li>'
+            var liElement = angular.element(liContent);
             ulElement.append(liElement);
-            liElement.on('click', function() {
-                closeContextMenu();
-                cleanupCtrl.showTaskDiskUsage(task);
-            });
+            if(dataService.selected_task_ids.length == 1) {
+                liElement.on('click', function() {
+                    closeContextMenu();
+                    cleanupCtrl.showTaskDiskUsage(task);
+                });
+            }
 
             var liElement = angular.element('<li><a href="#">Delete data</a></li>');
             ulElement.append(liElement);
             liElement.on('click', function() {
                 closeContextMenu();
-                cleanupCtrl.deleteTaskDataWithConfirmation(task);
+                cleanupCtrl.deleteSelectedTasksDataWithConfirmation();
             });
 
             var closeContextMenu = function(cme) {
diff --git a/SAS/ResourceAssignment/ResourceAssignmentEditor/lib/static/app/gantt-plugins/angular-gantt-contextmenu-plugin.js b/SAS/ResourceAssignment/ResourceAssignmentEditor/lib/static/app/gantt-plugins/angular-gantt-contextmenu-plugin.js
index cf1c495d70bde42aa0ef7e4015d7dc7022e0877e..33c7cb4d4343478167ad8846381754173584b884 100644
--- a/SAS/ResourceAssignment/ResourceAssignmentEditor/lib/static/app/gantt-plugins/angular-gantt-contextmenu-plugin.js
+++ b/SAS/ResourceAssignment/ResourceAssignmentEditor/lib/static/app/gantt-plugins/angular-gantt-contextmenu-plugin.js
@@ -35,7 +35,9 @@
                             if(!task)
                                 return;
 
-                            dataService.selected_task_id = task.id;
+                            if(!dataService.isTaskIdSelected(task.id)) {
+                                dataService.setSelectedTaskId(task.id);
+                            }
 
                             //search for already existing contextmenu element
                             while($document.find('#gantt-context-menu').length) {
@@ -59,7 +61,7 @@
 //                             liElement.on('click', function() {
 //                                 closeContextMenu();
 //                                 //TODO: remove link to dataService in this generic plugin
-//                                 dataService.copyTask(dScope.task.model.raTask);
+//                                 dataService.copyTask(task);
 //                             });
 
                             if(task.type == 'observation' && dataService.config.inspection_plots_base_url) {
@@ -67,23 +69,31 @@
                                 ulElement.append(liElement);
                                 liElement.on('click', function() {
                                     closeContextMenu();
-                                    var url = dataService.config.inspection_plots_base_url + '/' + task.otdb_id;
-                                    $window.open(url, '_blank');
+                                    var tasks = dataService.selected_task_ids.map(function(t_id) { return dataService.taskDict[t_id]; });
+                                    for(var t of tasks) {
+                                        if(t) {
+                                            var url = dataService.config.inspection_plots_base_url + '/' + t.otdb_id;
+                                            $window.open(url, '_blank');
+                                        }
+                                    }
                                 });
                             }
 
-                            var liElement = angular.element('<li><a href="#">Show disk usage</a></li>');
+                            var liContent = dataService.selected_task_ids.length == 1 ? '<li><a href="#">Show disk usage</a></li>' : '<li><a href="#" style="color:#aaaaaa">Show disk usage</a></li>'
+                            var liElement = angular.element(liContent);
                             ulElement.append(liElement);
-                            liElement.on('click', function() {
-                                closeContextMenu();
-                                cleanupCtrl.showTaskDiskUsage(dScope.task.model.raTask);
-                            });
+                            if(dataService.selected_task_ids.length == 1) {
+                                liElement.on('click', function() {
+                                    closeContextMenu();
+                                    cleanupCtrl.showTaskDiskUsage(task);
+                                });
+                            }
 
                             var liElement = angular.element('<li><a href="#">Delete data</a></li>');
                             ulElement.append(liElement);
                             liElement.on('click', function() {
                                 closeContextMenu();
-                                cleanupCtrl.deleteTaskDataWithConfirmation(dScope.task.model.raTask);
+                                cleanupCtrl.deleteSelectedTasksDataWithConfirmation();
                             });
 
                             var closeContextMenu = function() {
diff --git a/SAS/ResourceAssignment/ResourceAssignmentEditor/lib/templates/index.html b/SAS/ResourceAssignment/ResourceAssignmentEditor/lib/templates/index.html
index 4261f285027f4e47c2ea8fae426a7cbcc28605fd..c4267fd13be79ab693004f393c1998ec21c64ee5 100644
--- a/SAS/ResourceAssignment/ResourceAssignmentEditor/lib/templates/index.html
+++ b/SAS/ResourceAssignment/ResourceAssignmentEditor/lib/templates/index.html
@@ -75,12 +75,12 @@
                     <uib-timepicker ng-model="$parent.dataService.viewTimeSpan.to" ng-change="$parent.onViewTimeSpanToChanged()" hour-step="1" minute-step="5" show-meridian="false" show-spinners="false"></uib-timepicker>
                 </p>
             </div>
-            <div class="col-md-2">
+            <div class="col-md-1">
                 <label>Scroll:</label>
                 <p class="input-group">
                     <label title="Automatically scroll 'From' and 'To' to watch live events" style="padding-right: 4px; vertical-align: top;">Live <input type="checkbox" ng-model="$parent.dataService.autoFollowNow"></label>
                     <button title="Scroll back in time" type="button" class="btn btn-default" ng-click="scrollBack()"><i class="glyphicon glyphicon-step-backward"></i></button>
-                    <button title="Scroll forward in time"type="button" class="btn btn-default" ng-click="scrollForward()"><i class="glyphicon glyphicon-step-forward"></i></button>
+                    <button title="Scroll forward in time" type="button" class="btn btn-default" ng-click="scrollForward()"><i class="glyphicon glyphicon-step-forward"></i></button>
                 </p>
             </div>
             <div class="col-md-2">
@@ -89,6 +89,12 @@
                     <select class="form-control" ng-model="$parent.zoomTimespan" ng-options="option.name for option in $parent.zoomTimespans track by option.value" ng-change="$parent.onZoomTimespanChanged()"></select>
                 </p>
             </div>
+            <div class="col-md-1">
+                <label></label>
+                <p class="input-group">
+                    <button title="Show disk usage by project" type="button" class="btn btn-default" ng-click="cleanupCtrl.showAllProjectsDiskUsage()"><i class="glyphicon glyphicon-floppy-disk"></i></button>
+                </p>
+            </div>
         </div>
 
         <div class="top-stretch" ui-layout options="{flow: 'column'}">
diff --git a/SAS/ResourceAssignment/ResourceAssignmentEditor/lib/webservice.py b/SAS/ResourceAssignment/ResourceAssignmentEditor/lib/webservice.py
index 24bf2d58bb527a522116163f9ce17370be7beda8..d2492c6dd73a971856f354deca6bd2d6446896a6 100755
--- a/SAS/ResourceAssignment/ResourceAssignmentEditor/lib/webservice.py
+++ b/SAS/ResourceAssignment/ResourceAssignmentEditor/lib/webservice.py
@@ -277,13 +277,13 @@ def cleanupTaskData(task_id):
         if 'Content-Type' in request.headers and (request.headers['Content-Type'].startswith('application/json') or request.headers['Content-Type'].startswith('text/plain')):
             delete_params = json.loads(request.data)
 
-        print 'delete_params:', delete_params
-
         task = rarpc.getTask(task_id)
 
         if not task:
             abort(404, 'No such task (id=%s)' % task_id)
 
+        logger.info("cleanup task data id=%s otdb_id=%s delete_params=%s", task_id, task['otdb_id'], delete_params)
+
         result = curpc.removeTaskData(task['otdb_id'],
                                       delete_is=delete_params.get('delete_is', True),
                                       delete_cs=delete_params.get('delete_cs', True),