Commit 1cd15ddb by Sam Padgett Committed by GitHub

Merge pull request #150 from spadgett/project-list

Cache project list
parents eb1c5e84 32eadb7c
......@@ -2921,8 +2921,28 @@ angular.module('openshiftCommonServices')
angular.module('openshiftCommonServices')
.factory('ProjectsService',
function($location, $q, AuthService, DataService, annotationNameFilter, AuthorizationService, RecentlyViewedProjectsService) {
function($location,
$q,
$rootScope,
AuthService,
AuthorizationService,
DataService,
Logger,
RecentlyViewedProjectsService,
annotationNameFilter) {
// Cache project data when we can so we don't request it on every page load.
var cachedProjectData;
var cachedProjectDataIncomplete = false;
var clearCachedProjectData = function() {
Logger.debug('ProjectsService: clearing project cache');
cachedProjectData = null;
cachedProjectDataIncomplete = false;
};
AuthService.onUserChanged(clearCachedProjectData);
AuthService.onLogout(clearCachedProjectData);
var cleanEditableAnnotations = function(resource) {
var paths = [
......@@ -2957,6 +2977,10 @@ angular.module('openshiftCommonServices')
context.project = project;
context.projectPromise.resolve(project);
RecentlyViewedProjectsService.addProjectUID(project.metadata.uid);
if (cachedProjectData) {
cachedProjectData.update(project, 'MODIFIED');
}
// TODO: fix need to return context & projectPromise
return [project, context];
});
......@@ -2983,10 +3007,56 @@ angular.module('openshiftCommonServices')
});
});
},
// List the projects the user has access to. This method returns
// cached data if the projects had previously been fetched to avoid
// requesting them again and again, which is a problem for admins who
// might have hundreds or more.
list: function(forceRefresh) {
if (cachedProjectData && !forceRefresh) {
Logger.debug('ProjectsService: returning cached project data');
return $q.when(cachedProjectData);
}
Logger.debug('ProjectsService: listing projects, force refresh', forceRefresh);
return DataService.list('projects', {}).then(function(projectData) {
cachedProjectData = projectData;
return projectData;
}, function(error) {
// If the request fails, don't try to list projects again without `forceRefresh`.
cachedProjectData = {};
cachedProjectDataIncomplete = true;
});
},
isProjectListIncomplete: function() {
return cachedProjectDataIncomplete;
},
watch: function(context, callback) {
// Wrap `DataService.watch` so we can update the cached projects
// list on changes. TODO: We might want to disable watches entirely
// if we know the project list is large.
return DataService.watch('projects', context, function(projectData) {
cachedProjectData = projectData;
callback(projectData);
});
},
update: function(projectName, data) {
return DataService
.update('projects', projectName, cleanEditableAnnotations(data), {projectName: projectName}, {errorNotification: false});
return DataService.update('projects', projectName, cleanEditableAnnotations(data), {
projectName: projectName
}, {
errorNotification: false
}).then(function(updatedProject) {
if (cachedProjectData) {
cachedProjectData.update(updatedProject, 'MODIFIED');
}
return updatedProject;
});
},
create: function(name, displayName, description) {
var projectRequest = {
apiVersion: "v1",
......@@ -3001,11 +3071,25 @@ angular.module('openshiftCommonServices')
.create('projectrequests', null, projectRequest, {})
.then(function(project) {
RecentlyViewedProjectsService.addProjectUID(project.metadata.uid);
if (cachedProjectData) {
cachedProjectData.update(project, 'ADDED');
}
return project;
});
},
canCreate: function() {
return DataService.get("projectrequests", null, {}, { errorNotification: false});
},
delete: function(project) {
return DataService.delete('projects', project.metadata.name, {}).then(function(deletedProject) {
if (cachedProjectData) {
cachedProjectData.update(project, 'DELETED');
}
return deletedProject;
});
}
};
});
......
......@@ -310,11 +310,10 @@ hawtioPluginLoader.addModule('openshiftCommonUI');
" <!-- Use a form so that the enter key submits when typing a project name to confirm. -->\n" +
" <form>\n" +
" <div class=\"modal-body\">\n" +
" <h1>Are you sure you want to delete the project\n" +
" '<strong>{{displayName ? displayName : projectName}}</strong>'?</h1>\n" +
" <h1>Are you sure you want to delete the project '<strong>{{project | displayName}}</strong>'?</h1>\n" +
" <p>\n" +
" This will <strong>delete all resources</strong> associated with\n" +
" the project {{displayName ? displayName : projectName}} and <strong>cannot be\n" +
" the project {{project | displayName}} and <strong>cannot be\n" +
" undone</strong>. Make sure this is something you really want to do!\n" +
" </p>\n" +
" <div ng-show=\"typeNameToConfirm\">\n" +
......@@ -334,8 +333,8 @@ hawtioPluginLoader.addModule('openshiftCommonUI');
" </div>\n" +
" </div>\n" +
" <div class=\"modal-footer\">\n" +
" <button ng-disabled=\"typeNameToConfirm && confirmName !== projectName && confirmName !== displayName\" class=\"btn btn-lg btn-danger\" type=\"submit\" ng-click=\"delete();\">Delete</button>\n" +
" <button class=\"btn btn-lg btn-default\" type=\"button\" ng-click=\"cancel();\">Cancel</button>\n" +
" <button ng-disabled=\"typeNameToConfirm && confirmName !== project.metadata.name && confirmName !== (project | displayName : false)\" class=\"btn btn-lg btn-danger\" type=\"submit\" ng-click=\"delete()\">Delete</button>\n" +
" <button class=\"btn btn-lg btn-default\" type=\"button\" ng-click=\"cancel()\">Cancel</button>\n" +
" </div>\n" +
" </form>\n" +
"</div>\n"
......@@ -625,14 +624,12 @@ angular.module("openshiftCommonUI")
;'use strict';
angular.module("openshiftCommonUI")
.directive("deleteProject", function ($uibModal, $location, $filter, $q, hashSizeFilter, APIService, DataService, NotificationsService, Logger) {
.directive("deleteProject", function($uibModal, $location, $filter, $q, hashSizeFilter, APIService, NotificationsService, ProjectsService, Logger) {
return {
restrict: "E",
scope: {
// The name of project to delete
projectName: "@",
// Optional display name of the project to delete.
displayName: "@",
// The project to delete
project: "=",
// Set to true to disable the delete button.
disableDelete: "=?",
// Force the user to enter the name before we'll delete the project.
......@@ -658,6 +655,7 @@ angular.module("openshiftCommonUI")
// Replace so ".dropdown-menu > li > a" styles are applied.
replace: true,
link: function(scope, element, attrs) {
var displayName = $filter('displayName');
var navigateToList = function() {
if (scope.stayOnCurrentPage) {
return;
......@@ -692,14 +690,9 @@ angular.module("openshiftCommonUI")
modalInstance.result.then(function() {
// upon clicking delete button, delete resource and send alert
var projectName = scope.projectName;
var formattedResource = "Project \'" + (scope.displayName || projectName) + "\'";
var context = {};
DataService.delete({
resource: APIService.kindToResource("Project")
}, projectName, context)
.then(function() {
var formattedResource = "Project \'" + displayName(scope.project) + "\'";
ProjectsService.delete(scope.project).then(function() {
NotificationsService.addNotification({
type: "success",
message: formattedResource + " was marked for deletion."
......@@ -758,7 +751,14 @@ angular.module("openshiftCommonUI")
isDialog: '@'
},
templateUrl: 'src/components/edit-project/editProject.html',
controller: function($scope, $filter, $location, DataService, NotificationsService, annotationNameFilter, displayNameFilter, Logger) {
controller: function($scope,
$filter,
$location,
Logger,
NotificationsService,
ProjectsService,
annotationNameFilter,
displayNameFilter) {
if(!($scope.submitButtonLabel)) {
$scope.submitButtonLabel = 'Save';
}
......@@ -800,13 +800,10 @@ angular.module("openshiftCommonUI")
$scope.update = function() {
$scope.disableInputs = true;
if ($scope.editProjectForm.$valid) {
DataService
ProjectsService
.update(
'projects',
$scope.project.metadata.name,
cleanEditableAnnotations(mergeEditable($scope.project, $scope.editableFields)),
{projectName: $scope.project.name},
{errorNotification: false})
cleanEditableAnnotations(mergeEditable($scope.project, $scope.editableFields)))
.then(function(project) {
// angular is actually wrapping the redirect action :/
var cb = $scope.redirectAction();
......
......@@ -281,11 +281,10 @@ angular.module('openshiftCommonUI').run(['$templateCache', function($templateCac
" <!-- Use a form so that the enter key submits when typing a project name to confirm. -->\n" +
" <form>\n" +
" <div class=\"modal-body\">\n" +
" <h1>Are you sure you want to delete the project\n" +
" '<strong>{{displayName ? displayName : projectName}}</strong>'?</h1>\n" +
" <h1>Are you sure you want to delete the project '<strong>{{project | displayName}}</strong>'?</h1>\n" +
" <p>\n" +
" This will <strong>delete all resources</strong> associated with\n" +
" the project {{displayName ? displayName : projectName}} and <strong>cannot be\n" +
" the project {{project | displayName}} and <strong>cannot be\n" +
" undone</strong>. Make sure this is something you really want to do!\n" +
" </p>\n" +
" <div ng-show=\"typeNameToConfirm\">\n" +
......@@ -305,8 +304,8 @@ angular.module('openshiftCommonUI').run(['$templateCache', function($templateCac
" </div>\n" +
" </div>\n" +
" <div class=\"modal-footer\">\n" +
" <button ng-disabled=\"typeNameToConfirm && confirmName !== projectName && confirmName !== displayName\" class=\"btn btn-lg btn-danger\" type=\"submit\" ng-click=\"delete();\">Delete</button>\n" +
" <button class=\"btn btn-lg btn-default\" type=\"button\" ng-click=\"cancel();\">Cancel</button>\n" +
" <button ng-disabled=\"typeNameToConfirm && confirmName !== project.metadata.name && confirmName !== (project | displayName : false)\" class=\"btn btn-lg btn-danger\" type=\"submit\" ng-click=\"delete()\">Delete</button>\n" +
" <button class=\"btn btn-lg btn-default\" type=\"button\" ng-click=\"cancel()\">Cancel</button>\n" +
" </div>\n" +
" </form>\n" +
"</div>\n"
......
......@@ -2,11 +2,10 @@
<!-- Use a form so that the enter key submits when typing a project name to confirm. -->
<form>
<div class="modal-body">
<h1>Are you sure you want to delete the project
'<strong>{{displayName ? displayName : projectName}}</strong>'?</h1>
<h1>Are you sure you want to delete the project '<strong>{{project | displayName}}</strong>'?</h1>
<p>
This will <strong>delete all resources</strong> associated with
the project {{displayName ? displayName : projectName}} and <strong>cannot be
the project {{project | displayName}} and <strong>cannot be
undone</strong>. Make sure this is something you really want to do!
</p>
<div ng-show="typeNameToConfirm">
......@@ -26,8 +25,8 @@
</div>
</div>
<div class="modal-footer">
<button ng-disabled="typeNameToConfirm && confirmName !== projectName && confirmName !== displayName" class="btn btn-lg btn-danger" type="submit" ng-click="delete();">Delete</button>
<button class="btn btn-lg btn-default" type="button" ng-click="cancel();">Cancel</button>
<button ng-disabled="typeNameToConfirm && confirmName !== project.metadata.name && confirmName !== (project | displayName : false)" class="btn btn-lg btn-danger" type="submit" ng-click="delete()">Delete</button>
<button class="btn btn-lg btn-default" type="button" ng-click="cancel()">Cancel</button>
</div>
</form>
</div>
'use strict';
angular.module("openshiftCommonUI")
.directive("deleteProject", function ($uibModal, $location, $filter, $q, hashSizeFilter, APIService, DataService, NotificationsService, Logger) {
.directive("deleteProject", function($uibModal, $location, $filter, $q, hashSizeFilter, APIService, NotificationsService, ProjectsService, Logger) {
return {
restrict: "E",
scope: {
// The name of project to delete
projectName: "@",
// Optional display name of the project to delete.
displayName: "@",
// The project to delete
project: "=",
// Set to true to disable the delete button.
disableDelete: "=?",
// Force the user to enter the name before we'll delete the project.
......@@ -34,6 +32,7 @@ angular.module("openshiftCommonUI")
// Replace so ".dropdown-menu > li > a" styles are applied.
replace: true,
link: function(scope, element, attrs) {
var displayName = $filter('displayName');
var navigateToList = function() {
if (scope.stayOnCurrentPage) {
return;
......@@ -68,14 +67,9 @@ angular.module("openshiftCommonUI")
modalInstance.result.then(function() {
// upon clicking delete button, delete resource and send alert
var projectName = scope.projectName;
var formattedResource = "Project \'" + (scope.displayName || projectName) + "\'";
var context = {};
var formattedResource = "Project \'" + displayName(scope.project) + "\'";
DataService.delete({
resource: APIService.kindToResource("Project")
}, projectName, context)
.then(function() {
ProjectsService.delete(scope.project).then(function() {
NotificationsService.addNotification({
type: "success",
message: formattedResource + " was marked for deletion."
......
......@@ -13,7 +13,14 @@ angular.module("openshiftCommonUI")
isDialog: '@'
},
templateUrl: 'src/components/edit-project/editProject.html',
controller: function($scope, $filter, $location, DataService, NotificationsService, annotationNameFilter, displayNameFilter, Logger) {
controller: function($scope,
$filter,
$location,
Logger,
NotificationsService,
ProjectsService,
annotationNameFilter,
displayNameFilter) {
if(!($scope.submitButtonLabel)) {
$scope.submitButtonLabel = 'Save';
}
......@@ -55,13 +62,10 @@ angular.module("openshiftCommonUI")
$scope.update = function() {
$scope.disableInputs = true;
if ($scope.editProjectForm.$valid) {
DataService
ProjectsService
.update(
'projects',
$scope.project.metadata.name,
cleanEditableAnnotations(mergeEditable($scope.project, $scope.editableFields)),
{projectName: $scope.project.name},
{errorNotification: false})
cleanEditableAnnotations(mergeEditable($scope.project, $scope.editableFields)))
.then(function(project) {
// angular is actually wrapping the redirect action :/
var cb = $scope.redirectAction();
......
......@@ -2,8 +2,28 @@
angular.module('openshiftCommonServices')
.factory('ProjectsService',
function($location, $q, AuthService, DataService, annotationNameFilter, AuthorizationService, RecentlyViewedProjectsService) {
function($location,
$q,
$rootScope,
AuthService,
AuthorizationService,
DataService,
Logger,
RecentlyViewedProjectsService,
annotationNameFilter) {
// Cache project data when we can so we don't request it on every page load.
var cachedProjectData;
var cachedProjectDataIncomplete = false;
var clearCachedProjectData = function() {
Logger.debug('ProjectsService: clearing project cache');
cachedProjectData = null;
cachedProjectDataIncomplete = false;
};
AuthService.onUserChanged(clearCachedProjectData);
AuthService.onLogout(clearCachedProjectData);
var cleanEditableAnnotations = function(resource) {
var paths = [
......@@ -38,6 +58,10 @@ angular.module('openshiftCommonServices')
context.project = project;
context.projectPromise.resolve(project);
RecentlyViewedProjectsService.addProjectUID(project.metadata.uid);
if (cachedProjectData) {
cachedProjectData.update(project, 'MODIFIED');
}
// TODO: fix need to return context & projectPromise
return [project, context];
});
......@@ -64,10 +88,56 @@ angular.module('openshiftCommonServices')
});
});
},
// List the projects the user has access to. This method returns
// cached data if the projects had previously been fetched to avoid
// requesting them again and again, which is a problem for admins who
// might have hundreds or more.
list: function(forceRefresh) {
if (cachedProjectData && !forceRefresh) {
Logger.debug('ProjectsService: returning cached project data');
return $q.when(cachedProjectData);
}
Logger.debug('ProjectsService: listing projects, force refresh', forceRefresh);
return DataService.list('projects', {}).then(function(projectData) {
cachedProjectData = projectData;
return projectData;
}, function(error) {
// If the request fails, don't try to list projects again without `forceRefresh`.
cachedProjectData = {};
cachedProjectDataIncomplete = true;
});
},
isProjectListIncomplete: function() {
return cachedProjectDataIncomplete;
},
watch: function(context, callback) {
// Wrap `DataService.watch` so we can update the cached projects
// list on changes. TODO: We might want to disable watches entirely
// if we know the project list is large.
return DataService.watch('projects', context, function(projectData) {
cachedProjectData = projectData;
callback(projectData);
});
},
update: function(projectName, data) {
return DataService
.update('projects', projectName, cleanEditableAnnotations(data), {projectName: projectName}, {errorNotification: false});
return DataService.update('projects', projectName, cleanEditableAnnotations(data), {
projectName: projectName
}, {
errorNotification: false
}).then(function(updatedProject) {
if (cachedProjectData) {
cachedProjectData.update(updatedProject, 'MODIFIED');
}
return updatedProject;
});
},
create: function(name, displayName, description) {
var projectRequest = {
apiVersion: "v1",
......@@ -82,11 +152,25 @@ angular.module('openshiftCommonServices')
.create('projectrequests', null, projectRequest, {})
.then(function(project) {
RecentlyViewedProjectsService.addProjectUID(project.metadata.uid);
if (cachedProjectData) {
cachedProjectData.update(project, 'ADDED');
}
return project;
});
},
canCreate: function() {
return DataService.get("projectrequests", null, {}, { errorNotification: false});
},
delete: function(project) {
return DataService.delete('projects', project.metadata.name, {}).then(function(deletedProject) {
if (cachedProjectData) {
cachedProjectData.update(project, 'DELETED');
}
return deletedProject;
});
}
};
});
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment