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();
......
......@@ -481,11 +481,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" +
......@@ -505,8 +504,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"
......@@ -796,14 +795,12 @@ angular.module("openshiftCommonUI")
;'use strict';
angular.module("openshiftCommonUI")
.directive("deleteProject", ["$uibModal", "$location", "$filter", "$q", "hashSizeFilter", "APIService", "DataService", "NotificationsService", "Logger", function ($uibModal, $location, $filter, $q, hashSizeFilter, APIService, DataService, NotificationsService, Logger) {
.directive("deleteProject", ["$uibModal", "$location", "$filter", "$q", "hashSizeFilter", "APIService", "NotificationsService", "ProjectsService", "Logger", 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.
......@@ -829,6 +826,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;
......@@ -863,14 +861,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."
......@@ -929,7 +922,14 @@ angular.module("openshiftCommonUI")
isDialog: '@'
},
templateUrl: 'src/components/edit-project/editProject.html',
controller: ["$scope", "$filter", "$location", "DataService", "NotificationsService", "annotationNameFilter", "displayNameFilter", "Logger", function($scope, $filter, $location, DataService, NotificationsService, annotationNameFilter, displayNameFilter, Logger) {
controller: ["$scope", "$filter", "$location", "Logger", "NotificationsService", "ProjectsService", "annotationNameFilter", "displayNameFilter", function($scope,
$filter,
$location,
Logger,
NotificationsService,
ProjectsService,
annotationNameFilter,
displayNameFilter) {
if(!($scope.submitButtonLabel)) {
$scope.submitButtonLabel = 'Save';
}
......@@ -971,13 +971,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();
......@@ -4789,8 +4786,28 @@ angular.module('openshiftCommonServices')
angular.module('openshiftCommonServices')
.factory('ProjectsService',
["$location", "$q", "AuthService", "DataService", "annotationNameFilter", "AuthorizationService", "RecentlyViewedProjectsService", function($location, $q, AuthService, DataService, annotationNameFilter, AuthorizationService, RecentlyViewedProjectsService) {
["$location", "$q", "$rootScope", "AuthService", "AuthorizationService", "DataService", "Logger", "RecentlyViewedProjectsService", "annotationNameFilter", 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 = [
......@@ -4825,6 +4842,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];
});
......@@ -4851,10 +4872,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",
......@@ -4869,11 +4936,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;
});
}
};
}]);
......
......@@ -89,7 +89,7 @@ $templateCache.put("src/components/binding/bindApplicationForm.html", '<div clas
$templateCache.put("src/components/binding/bindResults.html", '<div ng-if="!ctrl.error">\n <div ng-if="!(ctrl.binding | isBindingReady)" class="bind-status" ng-class="{\'text-center\': !ctrl.progressInline, \'show-progress\': !ctrl.progressInline}">\n <div class="spinner" ng-class="{\'spinner-sm\': ctrl.progressInline, \'spinner-inline\': ctrl.progressInline, \'spinner-lg\': !ctrl.progressInline}" aria-hidden="true"></div>\n <h3 class="bind-message">\n <span class="sr-only">Pending</span>\n <div class="bind-pending-message" ng-class="{\'progress-inline\': ctrl.progressInline}">The binding was created but is not ready yet.</div>\n </h3>\n </div>\n <div ng-if="(ctrl.binding | isBindingReady)">\n <div class="bind-status">\n <span class="pficon pficon-ok" aria-hidden="true"></span>\n <span class="sr-only">Success</span>\n <h3 class="bind-message">\n <strong>{{ctrl.serviceToBind}}</strong>\n <span>has been bound</span>\n <span ng-if="ctrl.bindType === \'application\'"> to <strong>{{ctrl.applicationToBind}}</strong> successfully</span>\n </h3>\n </div>\n <div class="sub-title">\n The binding operation created the secret\n <a ng-if="ctrl.secretHref && \'secrets\' | canI : \'list\'"\n ng-href="{{ctrl.secretHref}}">{{ctrl.binding.spec.secretName}}</a>\n <span ng-if="!ctrl.secretHref || !(\'secrets\' | canI : \'list\')">{{ctrl.binding.spec.secretName}}</span>\n that you may need to reference in your application.\n <span ng-if="ctrl.showPodPresets">Its data will be available to your application as environment variables.</span>\n </div>\n <div class="alert alert-info bind-info">\n <span class="pficon pficon-info" aria-hidden="true"></span>\n <span class="sr-only">Info</span>\n The binding secret will only be available to new pods. You will need to redeploy your application.\n </div>\n </div>\n</div>\n<div ng-if="ctrl.error">\n <div class="bind-status">\n <span class="pficon pficon-error-circle-o text-danger" aria-hidden="true"></span>\n <span class="sr-only">Error</span>\n <h3 class="bind-message">\n <span>Binding Failed</span>\n </h3>\n </div>\n <div class="sub-title">\n <span ng-if="ctrl.error.data.message">\n {{ctrl.error.data.message | upperFirst}}\n </span>\n <span ng-if="!ctrl.error.data.message">\n An error occurred creating the binding.\n </span>\n </div>\n</div>\n'),
$templateCache.put("src/components/binding/bindServiceForm.html", '<div class="bind-form">\n <form>\n <div class="form-group">\n <label>\n <h3>Create a binding for <strong>{{ctrl.serviceClass.externalMetadata.displayName || ctrl.serviceClassName}}</strong></h3>\n </label>\n <span class="help-block">Bindings create a secret containing the necessary information for an application to use this service.</span>\n </div>\n </form>\n\n <form name="ctrl.formName" class="mar-bottom-lg">\n <fieldset>\n <div class="radio">\n <label class="bind-choice" ng-disabled="!ctrl.applications.length">\n <input type="radio" ng-model="ctrl.bindType" value="application" ng-disabled="!ctrl.applications.length">\n Create a secret and inject it into an application\n </label>\n <div class="application-select">\n <ui-select ng-model="ctrl.appToBind"\n ng-disabled="ctrl.bindType !== \'application\'"\n ng-required="ctrl.bindType === \'application\'">\n <ui-select-match placeholder="{{ctrl.applications.length ? \'Select an application\' : \'There are no applications in this project\'}}">\n <span>\n {{$select.selected.metadata.name}}\n <small class="text-muted">&ndash; {{$select.selected.kind | humanizeKind : true}}</small>\n </span>\n </ui-select-match>\n <ui-select-choices\n repeat="application in (ctrl.applications) | filter : { metadata: { name: $select.search } } track by (application | uid)"\n group-by="ctrl.groupByKind">\n <span ng-bind-html="application.metadata.name | highlight : $select.search"></span>\n </ui-select-choices>\n </ui-select>\n </div>\n <label class="bind-choice">\n <input type="radio" ng-model="ctrl.bindType" value="secret-only">\n Create a secret in <strong>{{ctrl.projectName}}</strong> to be used later\n </label>\n <div class="help-block bind-description">\n Secrets can be referenced later from an application.\n </div>\n <label ng-if="ctrl.allowNoBinding" class="bind-choice">\n <input type="radio" ng-model="ctrl.bindType" value="none">\n Do not bind at this time\n </label>\n <div ng-if="ctrl.allowNoBinding" class="help-block bind-description">\n Bindings can be created later from within a project.\n </div>\n </div>\n </fieldset>\n </form>\n</div>\n'),
$templateCache.put("src/components/create-project/createProject.html", '<form name="createProjectForm" novalidate>\n <fieldset ng-disabled="disableInputs">\n <div class="form-group">\n <label for="name" class="required">Name</label>\n <span ng-class="{\'has-error\': (createProjectForm.name.$error.pattern && createProjectForm.name.$touched) || nameTaken}">\n <input class="form-control"\n name="name"\n id="name"\n placeholder="my-project"\n type="text"\n required\n take-focus\n minlength="2"\n maxlength="63"\n pattern="[a-z0-9]([-a-z0-9]*[a-z0-9])?"\n aria-describedby="nameHelp"\n ng-model="name"\n ng-model-options="{ updateOn: \'default blur\' }"\n ng-change="nameTaken = false"\n autocorrect="off"\n autocapitalize="off"\n spellcheck="false">\n </span>\n <div>\n <span class="help-block">A unique name for the project.</span>\n </div>\n <div class="has-error">\n <span id="nameHelp" class="help-block" ng-if="createProjectForm.name.$error.required && createProjectForm.name.$dirty">\n Name is required.\n </span>\n </div>\n <div class="has-error">\n <span id="nameHelp" class="help-block" ng-if="createProjectForm.name.$error.minlength && createProjectForm.name.$touched">\n Name must have at least two characters.\n </span>\n </div>\n <div class="has-error">\n <span id="nameHelp" class="help-block" ng-if="createProjectForm.name.$error.pattern && createProjectForm.name.$touched">\n Project names may only contain lower-case letters, numbers, and dashes.\n They may not start or end with a dash.\n </span>\n </div>\n <div class="has-error">\n <span class="help-block" ng-if="nameTaken">\n This name is already in use. Please choose a different name.\n </span>\n </div>\n </div>\n\n <div class="form-group">\n <label for="displayName">Display Name</label>\n <input class="form-control"\n name="displayName"\n id="displayName"\n placeholder="My Project"\n type="text"\n ng-model="displayName">\n </div>\n\n <div class="form-group">\n <label for="description">Description</label>\n <textarea class="form-control"\n name="description"\n id="description"\n placeholder="A short description."\n ng-model="description"></textarea>\n </div>\n\n <div class="button-group">\n <button type="submit"\n class="btn btn-primary"\n ng-class="{\'dialog-btn\': isDialog}"\n ng-click="createProject()"\n ng-disabled="createProjectForm.$invalid || nameTaken || disableInputs"\n value="">\n Create\n </button>\n <button\n class="btn btn-default"\n ng-class="{\'dialog-btn\': isDialog}"\n ng-click="cancelCreateProject()">\n Cancel\n </button>\n </div>\n </fieldset>\n</form>\n'),
$templateCache.put("src/components/delete-project/delete-project-button.html", '<div class="actions">\n <!-- Avoid whitespace inside the link -->\n <a href=""\n ng-click="$event.stopPropagation(); openDeleteModal()"\n role="button"\n class="action-button"\n ng-attr-aria-disabled="{{disableDelete ? \'true\' : undefined}}"\n ng-class="{ \'disabled-link\': disableDelete }"\n ><i class="fa fa-trash-o" aria-hidden="true"\n ></i><span class="sr-only">Delete Project {{projectName}}</span></a>\n</div>\n'), $templateCache.put("src/components/delete-project/delete-project-modal.html", '<div class="delete-resource-modal">\n <!-- 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 <p>\n This will <strong>delete all resources</strong> associated with\n the project {{displayName ? displayName : projectName}} 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 <p>Type the name of the project to confirm.</p>\n <p>\n <label class="sr-only" for="resource-to-delete">project to delete</label>\n <input\n ng-model="confirmName"\n id="resource-to-delete"\n type="text"\n class="form-control input-lg"\n autocorrect="off"\n autocapitalize="off"\n spellcheck="false"\n autofocus>\n </p>\n </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 </div>\n </form>\n</div>\n'),
$templateCache.put("src/components/delete-project/delete-project-button.html", '<div class="actions">\n <!-- Avoid whitespace inside the link -->\n <a href=""\n ng-click="$event.stopPropagation(); openDeleteModal()"\n role="button"\n class="action-button"\n ng-attr-aria-disabled="{{disableDelete ? \'true\' : undefined}}"\n ng-class="{ \'disabled-link\': disableDelete }"\n ><i class="fa fa-trash-o" aria-hidden="true"\n ></i><span class="sr-only">Delete Project {{projectName}}</span></a>\n</div>\n'), $templateCache.put("src/components/delete-project/delete-project-modal.html", '<div class="delete-resource-modal">\n <!-- 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 \'<strong>{{project | displayName}}</strong>\'?</h1>\n <p>\n This will <strong>delete all resources</strong> associated with\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 <p>Type the name of the project to confirm.</p>\n <p>\n <label class="sr-only" for="resource-to-delete">project to delete</label>\n <input\n ng-model="confirmName"\n id="resource-to-delete"\n type="text"\n class="form-control input-lg"\n autocorrect="off"\n autocapitalize="off"\n spellcheck="false"\n autofocus>\n </p>\n </div>\n </div>\n <div class="modal-footer">\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'),
$templateCache.put("src/components/delete-project/delete-project.html", '<a href="javascript:void(0)"\n ng-click="openDeleteModal()"\n role="button"\n ng-attr-aria-disabled="{{disableDelete ? \'true\' : undefined}}"\n ng-class="{ \'disabled-link\': disableDelete }"\n>{{label || \'Delete\'}}</a>\n'), $templateCache.put("src/components/edit-project/editProject.html", '<form name="editProjectForm">\n <fieldset ng-disabled="disableInputs">\n <div class="form-group">\n <label for="displayName">Display Name</label>\n <input class="form-control"\n name="displayName"\n id="displayName"\n placeholder="My Project"\n type="text"\n ng-model="editableFields.displayName">\n </div>\n\n <div class="form-group">\n <label for="description">Description</label>\n <textarea class="form-control"\n name="description"\n id="description"\n placeholder="A short description."\n ng-model="editableFields.description"></textarea>\n </div>\n\n <div class="button-group">\n <button type="submit"\n class="btn btn-primary"\n ng-class="{\'dialog-btn\': isDialog}"\n ng-click="update()"\n ng-disabled="editProjectForm.$invalid || disableInputs"\n value="">{{submitButtonLabel}}</button>\n <button\n class="btn btn-default"\n ng-class="{\'dialog-btn\': isDialog}"\n ng-click="cancelEditProject()">\n Cancel\n </button>\n </div>\n </fieldset>\n</form>\n'),
$templateCache.put("src/components/origin-modal-popup/origin-modal-popup.html", '<div class="origin-modal-popup tile-click-prevent" ng-if="$ctrl.shown" ng-style="$ctrl.positionStyle"\n ng-class="{\'position-above\': $ctrl.showAbove, \'position-left\': $ctrl.showLeft}">\n <h4 class="origin-modal-popup-title">\n {{$ctrl.modalTitle}}\n </h4>\n <div ng-transclude></div>\n <a href="" class="origin-modal-popup-close" ng-click="$ctrl.onClose()">\n <span class="pficon pficon-close"></span>\n </a>\n</div>\n'), $templateCache.put("src/components/toast-notifications/toast-notifications.html", '<div class="toast-notifications-list-pf">\n <div ng-repeat="(notificationID, notification) in notifications track by (notificationID + (notification.message || notification.details))" ng-if="!notification.hidden || notification.isHover"\n ng-mouseenter="setHover(notification, true)" ng-mouseleave="setHover(notification, false)">\n <div class="toast-pf alert {{notification.type | alertStatus}}" ng-class="{\'alert-dismissable\': !hideCloseButton}">\n <button ng-if="!hideCloseButton" type="button" class="close" ng-click="close(notification)">\n <span class="pficon pficon-close" aria-hidden="true"></span>\n <span class="sr-only">Close</span>\n </button>\n <span class="{{notification.type | alertIcon}}" aria-hidden="true"></span>\n <span class="sr-only">{{notification.type}}</span>\n <span class="toast-notification-message" ng-if="notification.message">{{notification.message}}</span>\n <div ng-if="notification.details" class="toast-notification-details">\n <truncate-long-text\n limit="200"\n content="notification.details"\n use-word-boundary="true"\n expandable="true"\n hide-collapse="true">\n </truncate-long-text>\n </div>\n <span ng-repeat="link in notification.links">\n <a ng-if="!link.href" href="" ng-click="onClick(notification, link)" role="button">{{link.label}}</a>\n <a ng-if="link.href" ng-href="{{link.href}}" ng-attr-target="{{link.target}}">{{link.label}}</a>\n <span ng-if="!$last" class="toast-action-divider">|</span>\n </span>\n </div>\n </div>\n</div>\n'),
$templateCache.put("src/components/truncate-long-text/truncateLongText.html", '<!--\n Do not remove class `truncated-content` (here or below) even though it\'s not\n styled directly in origin-web-common. `truncated-content` is used by\n origin-web-console in certain contexts.\n-->\n<span ng-if="!truncated" ng-bind-html="content | highlightKeywords : keywords" class="truncated-content"></span>\n<span ng-if="truncated">\n <span ng-if="!toggles.expanded">\n <span ng-attr-title="{{content}}" class="truncation-block">\n <span ng-bind-html="truncatedContent | highlightKeywords : keywords" class="truncated-content"></span>&hellip;\n </span>\n <a ng-if="expandable" href="" ng-click="toggles.expanded = true" class="nowrap">See All</a>\n </span>\n <span ng-if="toggles.expanded">\n <div ng-if="prettifyJson" class="well">\n <span ng-if="!hideCollapse" class="pull-right" style="margin-top: -10px;"><a href="" ng-click="toggles.expanded = false" class="truncation-collapse-link">Collapse</a></span>\n <span ng-bind-html="content | prettifyJSON | highlightKeywords : keywords" class="pretty-json truncated-content"></span>\n </div>\n <span ng-if="!prettifyJson">\n <span ng-if="!hideCollapse" class="pull-right"><a href="" ng-click="toggles.expanded = false" class="truncation-collapse-link">Collapse</a></span>\n <span ng-bind-html="content | highlightKeywords : keywords" class="truncated-content"></span>\n </span>\n </span>\n</span>\n');
......@@ -197,12 +197,11 @@ cb && cb();
}, $scope.$on("$destroy", hideErrorNotifications);
} ]
};
} ]), angular.module("openshiftCommonUI").directive("deleteProject", [ "$uibModal", "$location", "$filter", "$q", "hashSizeFilter", "APIService", "DataService", "NotificationsService", "Logger", function($uibModal, $location, $filter, $q, hashSizeFilter, APIService, DataService, NotificationsService, Logger) {
} ]), angular.module("openshiftCommonUI").directive("deleteProject", [ "$uibModal", "$location", "$filter", "$q", "hashSizeFilter", "APIService", "NotificationsService", "ProjectsService", "Logger", function($uibModal, $location, $filter, $q, hashSizeFilter, APIService, NotificationsService, ProjectsService, Logger) {
return {
restrict:"E",
scope:{
projectName:"@",
displayName:"@",
project:"=",
disableDelete:"=?",
typeNameToConfirm:"=?",
label:"@?",
......@@ -216,7 +215,7 @@ return angular.isDefined(attr.buttonOnly) ? "src/components/delete-project/delet
},
replace:!0,
link:function(scope, element, attrs) {
var navigateToList = function() {
var displayName = $filter("displayName"), navigateToList = function() {
if (!scope.stayOnCurrentPage) {
if (scope.redirectUrl) return void $location.url(scope.redirectUrl);
if ("/" === $location.path()) return void scope.$emit("deleteProject");
......@@ -233,10 +232,8 @@ controller:"DeleteProjectModalController",
scope:scope
});
modalInstance.result.then(function() {
var projectName = scope.projectName, formattedResource = "Project '" + (scope.displayName || projectName) + "'", 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."
......@@ -270,7 +267,7 @@ onCancel:"&",
isDialog:"@"
},
templateUrl:"src/components/edit-project/editProject.html",
controller:[ "$scope", "$filter", "$location", "DataService", "NotificationsService", "annotationNameFilter", "displayNameFilter", "Logger", function($scope, $filter, $location, DataService, NotificationsService, annotationNameFilter, displayNameFilter, Logger) {
controller:[ "$scope", "$filter", "$location", "Logger", "NotificationsService", "ProjectsService", "annotationNameFilter", "displayNameFilter", function($scope, $filter, $location, Logger, NotificationsService, ProjectsService, annotationNameFilter, displayNameFilter) {
$scope.submitButtonLabel || ($scope.submitButtonLabel = "Save"), $scope.isDialog = "true" === $scope.isDialog;
var annotation = $filter("annotation"), annotationName = $filter("annotationName"), editableFields = function(resource) {
return {
......@@ -287,11 +284,7 @@ resource.metadata.annotations[path] || delete resource.metadata.annotations[path
}), resource;
};
$scope.editableFields = editableFields($scope.project), $scope.update = function() {
$scope.disableInputs = !0, $scope.editProjectForm.$valid && DataService.update("projects", $scope.project.metadata.name, cleanEditableAnnotations(mergeEditable($scope.project, $scope.editableFields)), {
projectName:$scope.project.name
}, {
errorNotification:!1
}).then(function(project) {
$scope.disableInputs = !0, $scope.editProjectForm.$valid && ProjectsService.update($scope.project.metadata.name, cleanEditableAnnotations(mergeEditable($scope.project, $scope.editableFields))).then(function(project) {
var cb = $scope.redirectAction();
cb && cb(encodeURIComponent($scope.project.metadata.name)), NotificationsService.addNotification({
type:"success",
......@@ -1989,7 +1982,11 @@ token ? (authLogger.log("LocalStorageUserStore.setToken", token, ttl), localStor
}
};
} ];
}), angular.module("openshiftCommonServices").factory("ProjectsService", [ "$location", "$q", "AuthService", "DataService", "annotationNameFilter", "AuthorizationService", "RecentlyViewedProjectsService", function($location, $q, AuthService, DataService, annotationNameFilter, AuthorizationService, RecentlyViewedProjectsService) {
}), angular.module("openshiftCommonServices").factory("ProjectsService", [ "$location", "$q", "$rootScope", "AuthService", "AuthorizationService", "DataService", "Logger", "RecentlyViewedProjectsService", "annotationNameFilter", function($location, $q, $rootScope, AuthService, AuthorizationService, DataService, Logger, RecentlyViewedProjectsService, annotationNameFilter) {
var cachedProjectData, cachedProjectDataIncomplete = !1, clearCachedProjectData = function() {
Logger.debug("ProjectsService: clearing project cache"), cachedProjectData = null, cachedProjectDataIncomplete = !1;
};
AuthService.onUserChanged(clearCachedProjectData), AuthService.onLogout(clearCachedProjectData);
var cleanEditableAnnotations = function(resource) {
var paths = [ annotationNameFilter("description"), annotationNameFilter("displayName") ];
return _.each(paths, function(path) {
......@@ -2008,7 +2005,7 @@ return DataService.get("projects", projectName, context, {
errorNotification:!1
}).then(function(project) {
return AuthorizationService.getProjectRules(projectName).then(function() {
return context.project = project, context.projectPromise.resolve(project), RecentlyViewedProjectsService.addProjectUID(project.metadata.uid), [ project, context ];
return context.project = project, context.projectPromise.resolve(project), RecentlyViewedProjectsService.addProjectUID(project.metadata.uid), cachedProjectData && cachedProjectData.update(project, "MODIFIED"), [ project, context ];
});
}, function(e) {
context.projectPromise.reject(e);
......@@ -2020,11 +2017,28 @@ error_description:description
});
});
},
list:function(forceRefresh) {
return cachedProjectData && !forceRefresh ? (Logger.debug("ProjectsService: returning cached project data"), $q.when(cachedProjectData)) :(Logger.debug("ProjectsService: listing projects, force refresh", forceRefresh), DataService.list("projects", {}).then(function(projectData) {
return cachedProjectData = projectData, projectData;
}, function(error) {
cachedProjectData = {}, cachedProjectDataIncomplete = !0;
}));
},
isProjectListIncomplete:function() {
return cachedProjectDataIncomplete;
},
watch:function(context, callback) {
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:!1
}).then(function(updatedProject) {
return cachedProjectData && cachedProjectData.update(updatedProject, "MODIFIED"), updatedProject;
});
},
create:function(name, displayName, description) {
......@@ -2038,13 +2052,18 @@ displayName:displayName,
description:description
};
return DataService.create("projectrequests", null, projectRequest, {}).then(function(project) {
return RecentlyViewedProjectsService.addProjectUID(project.metadata.uid), project;
return RecentlyViewedProjectsService.addProjectUID(project.metadata.uid), cachedProjectData && cachedProjectData.update(project, "ADDED"), project;
});
},
canCreate:function() {
return DataService.get("projectrequests", null, {}, {
errorNotification:!1
});
},
"delete":function(project) {
return DataService["delete"]("projects", project.metadata.name, {}).then(function(deletedProject) {
return cachedProjectData && cachedProjectData.update(project, "DELETED"), deletedProject;
});
}
};
} ]), angular.module("openshiftCommonServices").service("RecentlyViewedProjectsService", [ "$filter", function($filter) {
......
......@@ -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