Skip to content

Commit 7c1f513

Browse files
committed
Don't requests projects on every page load
1 parent bb4cdb5 commit 7c1f513

File tree

10 files changed

+407
-275
lines changed

10 files changed

+407
-275
lines changed

app/scripts/constants.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ angular.extend(window.OPENSHIFT_CONSTANTS, {
8787

8888
ENABLE_TECH_PREVIEW_FEATURE: {
8989
// Enable the new landing page and service catalog experience
90-
service_catalog_landing_page: false,
90+
service_catalog_landing_page: true,
9191
// Set to `true` when the template service broker is enabled for the cluster in master-config.yaml
9292
template_service_broker: false,
9393
pod_presets: false

app/scripts/controllers/createFromURL.js

+1-2
Original file line numberDiff line numberDiff line change
@@ -156,8 +156,7 @@ angular.module('openshiftConsole')
156156
$scope.projects = {};
157157
$scope.canCreateProject = undefined;
158158

159-
DataService
160-
.list("projects", $scope)
159+
ProjectsService.list()
161160
.then(function(items) {
162161
$scope.loaded = true;
163162
$scope.projects = $filter('orderByDisplayName')(items.by("metadata.name"));

app/scripts/controllers/membership.js

+1-2
Original file line numberDiff line numberDiff line change
@@ -243,8 +243,7 @@ angular
243243
$scope.user = resp;
244244
});
245245

246-
DataService
247-
.list('projects', {})
246+
ProjectsService.list()
248247
.then(function(resp) {
249248
var projects = _.keys(resp.by('metadata.name')).sort();
250249
angular.extend($scope, {

app/scripts/controllers/projects.js

+48-12
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,15 @@ angular.module('openshiftConsole')
1616
AuthService,
1717
DataService,
1818
KeywordService,
19+
Navigate,
1920
Logger,
2021
ProjectsService) {
22+
var MAX_PROJETS_TO_WATCH = 500;
23+
2124
var projects, sortedProjects;
2225
var watches = [];
2326
var filterKeywords = [];
27+
var watchingProjects = false;
2428

2529
$scope.alerts = $scope.alerts || {};
2630
$scope.loading = true;
@@ -62,19 +66,19 @@ angular.module('openshiftConsole')
6266
// Sort by display name. Use `metadata.name` as a secondary sort when
6367
// projects have the same display name.
6468
sortedProjects = _.orderBy(projects,
65-
[ displayNameLower, 'metadata.name' ],
66-
[ primarySortOrder ]);
69+
[ displayNameLower, 'metadata.name' ],
70+
[ primarySortOrder ]);
6771
break;
6872
case 'metadata.annotations["openshift.io/requester"]':
6973
// Sort by requester, then display name. Secondary sort is always ascending.
7074
sortedProjects = _.orderBy(projects,
71-
[ sortID, displayNameLower ],
72-
[ primarySortOrder, 'asc' ]);
75+
[ sortID, displayNameLower ],
76+
[ primarySortOrder, 'asc' ]);
7377
break;
7478
default:
7579
sortedProjects = _.orderBy(projects,
76-
[ sortID ],
77-
[ primarySortOrder ]);
80+
[ sortID ],
81+
[ primarySortOrder ]);
7882
}
7983

8084
// Remember the previous sort ID.
@@ -109,6 +113,21 @@ angular.module('openshiftConsole')
109113
onSortChange: update
110114
};
111115

116+
var updateProjects = function(projectData) {
117+
projects = _.toArray(projectData.by("metadata.name"));
118+
$scope.loading = false;
119+
$scope.showGetStarted = _.isEmpty(projects) && !$scope.isProjectListIncomplete;
120+
update();
121+
};
122+
123+
// On create / edit / delete, manually update the project list if not
124+
// watching. This uses cached project data, so is not expensive.
125+
var onChanges = function() {
126+
if (!watchingProjects) {
127+
ProjectsService.list().then(updateProjects);
128+
}
129+
};
130+
112131
$scope.newProjectPanelShown = false;
113132

114133
$scope.createProject = function() {
@@ -121,6 +140,7 @@ angular.module('openshiftConsole')
121140

122141
$scope.onNewProject = function() {
123142
$scope.newProjectPanelShown = false;
143+
onChanges();
124144
};
125145

126146
$scope.editProjectPanelShown = false;
@@ -136,6 +156,13 @@ angular.module('openshiftConsole')
136156

137157
$scope.onEditProject = function() {
138158
$scope.editProjectPanelShown = false;
159+
onChanges();
160+
};
161+
162+
$scope.onDeleteProject = onChanges;
163+
164+
$scope.goToProject = function(projectName) {
165+
Navigate.toProjectOverview(projectName);
139166
};
140167

141168
$scope.$watch('search.text', _.debounce(function(searchText) {
@@ -144,16 +171,25 @@ angular.module('openshiftConsole')
144171
}, 50, { maxWait: 250 }));
145172

146173
AuthService.withUser().then(function() {
147-
watches.push(DataService.watch("projects", $scope, function(projectData) {
148-
projects = _.toArray(projectData.by("metadata.name"));
174+
ProjectsService.list().then(function(projectData) {
175+
$scope.isProjectListIncomplete = ProjectsService.isProjectListIncomplete();
176+
updateProjects(projectData);
177+
if (_.size(projects) <= MAX_PROJETS_TO_WATCH) {
178+
watches.push(ProjectsService.watch($scope, updateProjects));
179+
watchingProjects = true;
180+
}
181+
// DEBUG
182+
$scope.isProjectListIncomplete = true;
183+
}, function() {
184+
$scope.isProjectListIncomplete = true;
149185
$scope.loading = false;
150-
$scope.showGetStarted = _.isEmpty(projects);
186+
projects = [];
151187
update();
152-
}));
188+
});
153189
});
154190

155-
// Test if the user can submit project requests. Handle error notifications
156-
// ourselves because 403 responses are expected.
191+
// Test if the user can submit project requests. Handle error notifications
192+
// ourselves because 403 responses are expected.
157193
ProjectsService
158194
.canCreate()
159195
.then(function() {

app/scripts/directives/istagSelect.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ angular.module("openshiftConsole")
1919
* selectDisabled:
2020
* An expression that will disable the form (default: false)
2121
*/
22-
.directive("istagSelect", function(DataService) {
22+
.directive("istagSelect", function(DataService, ProjectsService) {
2323
return {
2424
require: '^form',
2525
restrict: 'E',
@@ -81,7 +81,7 @@ angular.module("openshiftConsole")
8181
});
8282
};
8383

84-
DataService.list("projects", {}, function(projectData) {
84+
ProjectsService.list().then(function(projectData) {
8585
$scope.namespaces = _.keys(projectData.by('metadata.name'));
8686

8787
if ($scope.includeSharedNamespace) {

app/scripts/directives/nav.js

+32-10
Original file line numberDiff line numberDiff line change
@@ -58,16 +58,21 @@ angular.module('openshiftConsole')
5858
}
5959
};
6060
})
61-
.directive('projectHeader', function($timeout, $location, $filter, DataService, projectOverviewURLFilter, Constants) {
61+
.directive('projectHeader', function($timeout, $location, $filter, ProjectsService, projectOverviewURLFilter, Constants) {
6262

6363
// cache these to eliminate flicker
6464
var projects = {};
6565
var sortedProjects = [];
6666

67+
var displayName = $filter('displayName');
68+
var uniqueDisplayName = $filter('uniqueDisplayName');
69+
6770
return {
6871
restrict: 'EA',
6972
templateUrl: 'views/directives/header/project-header.html',
7073
link: function($scope, $elem) {
74+
var MAX_PROJETS_TO_DISPLAY = 100;
75+
7176
$scope.closeOrderingPanel = function() {
7277
_.set($scope, 'ordering.panelName', "");
7378
};
@@ -108,23 +113,40 @@ angular.module('openshiftConsole')
108113
projects[name] = project;
109114
}
110115

111-
sortedProjects = $filter('orderByDisplayName')(projects);
112-
options = _.map(sortedProjects, function(item) {
113-
return $('<option>')
114-
.attr("value", item.metadata.name)
115-
.attr("selected", item.metadata.name === name)
116-
.text($filter("uniqueDisplayName")(item, sortedProjects));
117-
});
116+
var makeOption = function(project, skipUniqueCheck) {
117+
var option = $('<option>').attr("value", project.metadata.name).attr("selected", project.metadata.name === name);
118+
if (skipUniqueCheck) {
119+
option.text(displayName(project));
120+
} else {
121+
// FIXME: This is pretty inefficient, but probably OK if
122+
// MAX_PROJETS_TO_DISPLAY is not too large.
123+
option.text(uniqueDisplayName(project, sortedProjects));
124+
}
125+
126+
return option;
127+
};
128+
129+
// Only show all projects in the dropdown if less than a max number.
130+
// Otherwise it's not usable and might impact performance.
131+
if (_.size(projects) <= MAX_PROJETS_TO_DISPLAY) {
132+
sortedProjects = $filter('orderByDisplayName')(projects);
133+
options = _.map(sortedProjects, function(project) {
134+
return makeOption(project, false);
135+
});
136+
} else {
137+
// Show the current project and a "View all Projects" link.
138+
options = [ makeOption(projects[name], true) ];
139+
}
118140

119141
select.empty();
120142
select.append(options);
121143
select.append($('<option data-divider="true"></option>'));
122-
select.append($('<option value="">View all projects</option>'));
144+
select.append($('<option value="">View all Projects</option>'));
123145
select.selectpicker('refresh');
124146
};
125147

126148

127-
DataService.list("projects", $scope, function(items) {
149+
ProjectsService.list().then(function(items) {
128150
projects = items.by("metadata.name");
129151
updateOptions();
130152
});

app/views/projects.html

+44-9
Original file line numberDiff line numberDiff line change
@@ -64,12 +64,46 @@ <h1>My Projects</h1>
6464
</div>
6565
</div>
6666
</div>
67-
<div ng-if="!projects.length" class="h3">
67+
<p ng-if="isProjectListIncomplete">
68+
<div class="alert alert-warning">
69+
<span class="pficon pficon-warning-triangle-o" aria-hidden="true"></span>
70+
<span class="sr-only">Warning:</span>
71+
The complete list of your projects could not be loaded.
72+
Type a project name to go to that project.
73+
</div>
74+
<form>
75+
<div class="form-group">
76+
<label for="typed-project-name">Project Name</label>
77+
<div class="input-group">
78+
<input
79+
class="form-control"
80+
type="text"
81+
id="typed-project-name"
82+
required
83+
minlength="2"
84+
ng-model="input.typedProjectName"
85+
autocorrect="off"
86+
autocapitalize="none"
87+
spellcheck="false">
88+
<span class="input-group-btn">
89+
<button class="btn btn-default"
90+
type="submit"
91+
ng-disabled="!input.typedProjectName"
92+
ng-click="goToProject(input.typedProjectName)">
93+
<i class="fa fa-arrow-right" aria-hidden="true"></i>
94+
<span class="sr-only">Go to Project</span>
95+
</button>
96+
</span>
97+
</div>
98+
</div>
99+
</form>
100+
</p>
101+
<div ng-if="!projects.length && !isProjectListIncomplete" class="h3">
68102
The current filter is hiding all projects.
69103
<a href="" ng-click="search.text = ''" role="button">Clear Filter</a>
70104
</div>
71105
<div class="list-group list-view-pf projects-list">
72-
<div ng-repeat="project in projects" class="list-group-item project-info tile-click">
106+
<div ng-repeat="project in projects | limitTo: 500 track by (project | uid)" class="list-group-item project-info tile-click">
73107
<div class="list-view-pf-main-info">
74108
<div class="list-view-pf-description project-names">
75109
<div class="list-group-item-heading project-name-item">
@@ -110,16 +144,14 @@ <h2 class="h1">
110144
</a>
111145
</li>
112146
<li role="menuitem">
113-
<delete-link
114-
kind="Project"
147+
<delete-project
115148
label="Delete Project"
116-
resource-name="{{project.metadata.name}}"
117-
project-name="{{project.metadata.name}}"
118-
display-name="{{(project | displayName)}}"
149+
project="project"
119150
type-name-to-confirm="true"
120151
stay-on-current-page="true"
121-
alerts="alerts">
122-
</delete-link>
152+
alerts="alerts"
153+
success="onDeleteProject">
154+
</delete-project>
123155
</li>
124156
</ul>
125157
</div>
@@ -131,6 +163,9 @@ <h2 class="h1">
131163
</origin-modal-popup>
132164
</div>
133165
</div>
166+
<p ng-if="projects.length > 500">
167+
Only the first 500 projects are displayed.
168+
</p>
134169
<p class="projects-instructions" ng-if="canCreate === false" ng-include="'views/_cannot-create-project.html'"></p>
135170
</div>
136171
</div>

0 commit comments

Comments
 (0)