Skip to content

Commit c9a5d1a

Browse files
author
OpenShift Bot
authored
Merge pull request #1956 from spadgett/projects-list
Merged by openshift-bot
2 parents 5972dde + 7ab78e3 commit c9a5d1a

File tree

11 files changed

+632
-440
lines changed

11 files changed

+632
-440
lines changed

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

+51-14
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 = 250;
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;
@@ -30,6 +34,9 @@ angular.module('openshiftConsole')
3034
text: ''
3135
};
3236

37+
// Only show the first `MAX_PROJETS_TO_WATCH` on the page. Users can always filter.
38+
$scope.limitListTo = MAX_PROJETS_TO_WATCH;
39+
3340
var filterFields = [
3441
'metadata.name',
3542
'metadata.annotations["openshift.io/display-name"]',
@@ -62,19 +69,19 @@ angular.module('openshiftConsole')
6269
// Sort by display name. Use `metadata.name` as a secondary sort when
6370
// projects have the same display name.
6471
sortedProjects = _.orderBy(projects,
65-
[ displayNameLower, 'metadata.name' ],
66-
[ primarySortOrder ]);
72+
[ displayNameLower, 'metadata.name' ],
73+
[ primarySortOrder ]);
6774
break;
6875
case 'metadata.annotations["openshift.io/requester"]':
6976
// Sort by requester, then display name. Secondary sort is always ascending.
7077
sortedProjects = _.orderBy(projects,
71-
[ sortID, displayNameLower ],
72-
[ primarySortOrder, 'asc' ]);
78+
[ sortID, displayNameLower ],
79+
[ primarySortOrder, 'asc' ]);
7380
break;
7481
default:
7582
sortedProjects = _.orderBy(projects,
76-
[ sortID ],
77-
[ primarySortOrder ]);
83+
[ sortID ],
84+
[ primarySortOrder ]);
7885
}
7986

8087
// Remember the previous sort ID.
@@ -109,6 +116,21 @@ angular.module('openshiftConsole')
109116
onSortChange: update
110117
};
111118

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

114136
$scope.createProject = function() {
@@ -121,6 +143,7 @@ angular.module('openshiftConsole')
121143

122144
$scope.onNewProject = function() {
123145
$scope.newProjectPanelShown = false;
146+
onChanges();
124147
};
125148

126149
$scope.editProjectPanelShown = false;
@@ -136,24 +159,38 @@ angular.module('openshiftConsole')
136159

137160
$scope.onEditProject = function() {
138161
$scope.editProjectPanelShown = false;
162+
onChanges();
163+
};
164+
165+
$scope.onDeleteProject = onChanges;
166+
167+
$scope.goToProject = function(projectName) {
168+
Navigate.toProjectOverview(projectName);
139169
};
140170

141171
$scope.$watch('search.text', _.debounce(function(searchText) {
142172
$scope.keywords = filterKeywords = KeywordService.generateKeywords(searchText);
143-
$scope.$apply(filterProjects);
144-
}, 50, { maxWait: 250 }));
173+
$scope.$applyAsync(filterProjects);
174+
}, 350));
145175

146176
AuthService.withUser().then(function() {
147-
watches.push(DataService.watch("projects", $scope, function(projectData) {
148-
projects = _.toArray(projectData.by("metadata.name"));
177+
ProjectsService.list().then(function(projectData) {
178+
$scope.isProjectListIncomplete = ProjectsService.isProjectListIncomplete();
179+
updateProjects(projectData);
180+
if (!$scope.isProjectListIncomplete && _.size(projects) <= MAX_PROJETS_TO_WATCH) {
181+
watches.push(ProjectsService.watch($scope, updateProjects));
182+
watchingProjects = true;
183+
}
184+
}, function() {
185+
$scope.isProjectListIncomplete = true;
149186
$scope.loading = false;
150-
$scope.showGetStarted = _.isEmpty(projects);
187+
projects = [];
151188
update();
152-
}));
189+
});
153190
});
154191

155-
// Test if the user can submit project requests. Handle error notifications
156-
// ourselves because 403 responses are expected.
192+
// Test if the user can submit project requests. Handle error notifications
193+
// ourselves because 403 responses are expected.
157194
ProjectsService
158195
.canCreate()
159196
.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

+45-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+
<div 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+
</div>
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: limitListTo 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,13 @@ <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+
success="onDeleteProject">
153+
</delete-project>
123154
</li>
124155
</ul>
125156
</div>
@@ -131,6 +162,11 @@ <h2 class="h1">
131162
</origin-modal-popup>
132163
</div>
133164
</div>
165+
<p ng-if="projects.length > limitListTo">
166+
Only the first {{limitListTo}} projects are displayed.
167+
Filter by keyword or change sort options to see other
168+
projects.
169+
</p>
134170
<p class="projects-instructions" ng-if="canCreate === false" ng-include="'views/_cannot-create-project.html'"></p>
135171
</div>
136172
</div>

bower.json

+3-3
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
"angular-bootstrap": "0.14.3",
1616
"angular-patternfly": "4.3.0",
1717
"angular-gettext": "2.3.9",
18-
"uri.js": "1.18.0",
18+
"uri.js": "1.18.12",
1919
"moment": "2.14.2",
2020
"moment-timezone": "0.5.3",
2121
"patternfly": "3.26.1",
@@ -46,8 +46,8 @@
4646
"angular-moment": "1.0.0",
4747
"angular-utf8-base64": "0.0.5",
4848
"file-saver": "1.3.3",
49-
"origin-web-common": "0.0.46",
50-
"origin-web-catalog": "0.0.38"
49+
"origin-web-common": "0.0.47",
50+
"origin-web-catalog": "0.0.39"
5151
},
5252
"devDependencies": {
5353
"angular-mocks": "1.5.11",

0 commit comments

Comments
 (0)