|
4 | 4 | angular.module('openshiftConsole').component('processTemplateDialog', {
|
5 | 5 | controller: [
|
6 | 6 | '$scope',
|
| 7 | + '$filter', |
| 8 | + '$timeout', |
| 9 | + 'Catalog', |
7 | 10 | 'DataService',
|
| 11 | + 'KeywordService', |
| 12 | + 'NotificationsService', |
| 13 | + 'ProjectsService', |
| 14 | + 'RecentlyViewedProjectsService', |
8 | 15 | ProcessTemplateDialog
|
9 | 16 | ],
|
10 | 17 | controllerAs: '$ctrl',
|
11 | 18 | bindings: {
|
12 | 19 | template: '<',
|
| 20 | + project: '<', |
| 21 | + useProjectTemplate: '<', |
13 | 22 | onDialogClosed: '&'
|
14 | 23 | },
|
15 | 24 | templateUrl: 'views/directives/process-template-dialog.html'
|
16 | 25 | });
|
17 | 26 |
|
18 |
| - function ProcessTemplateDialog($scope, DataService) { |
| 27 | + function ProcessTemplateDialog($scope, |
| 28 | + $filter, |
| 29 | + $timeout, |
| 30 | + Catalog, |
| 31 | + DataService, |
| 32 | + KeywordService, |
| 33 | + NotificationsService, |
| 34 | + ProjectsService, |
| 35 | + RecentlyViewedProjectsService) { |
19 | 36 | var ctrl = this;
|
20 | 37 | var validityWatcher;
|
| 38 | + var projectListWatcher; |
| 39 | + var MAX_PROJECTS_TO_WATCH = 250; |
| 40 | + |
| 41 | + ctrl.selectStep = { |
| 42 | + id: 'projectTemplates', |
| 43 | + label: 'Selection', |
| 44 | + view: 'views/directives/process-template-dialog/process-template-select.html', |
| 45 | + hidden: ctrl.useProjectTemplate !== true, |
| 46 | + allowed: true, |
| 47 | + valid: false, |
| 48 | + onShow: showSelect |
| 49 | + }; |
21 | 50 |
|
22 | 51 | ctrl.configStep = {
|
23 | 52 | id: 'configuration',
|
|
43 | 72 |
|
44 | 73 | ctrl.$onInit = function() {
|
45 | 74 | ctrl.loginBaseUrl = DataService.openshiftAPIBaseUrl();
|
| 75 | + ctrl.preSelectedProject = ctrl.selectedProject = ctrl.project; |
| 76 | + listProjects(); |
| 77 | + |
| 78 | + ctrl.projectEmptyState = { |
| 79 | + icon: 'pficon pficon-info', |
| 80 | + title: 'No Project Selected', |
| 81 | + info: 'Please select a project from the dropdown to load Templates and Images from that project' |
| 82 | + }; |
| 83 | + |
| 84 | + ctrl.templatesEmptyState = { |
| 85 | + icon: 'pficon pficon-info', |
| 86 | + title: 'No Templates or Images', |
| 87 | + info: 'The selected project has no templates or images available to import' |
| 88 | + }; |
| 89 | + |
| 90 | + ctrl.filterConfig = { |
| 91 | + fields: [ |
| 92 | + { |
| 93 | + id: 'keyword', |
| 94 | + title: 'Keyword', |
| 95 | + placeholder: 'Filter by Keyword', |
| 96 | + filterType: 'text' |
| 97 | + } |
| 98 | + ], |
| 99 | + resultsCount: 0, |
| 100 | + appliedFilters: [], |
| 101 | + onFilterChange: filterChange |
| 102 | + }; |
46 | 103 | };
|
47 | 104 |
|
48 | 105 | ctrl.$onChanges = function(changes) {
|
|
52 | 109 | ctrl.iconClass = getIconClass();
|
53 | 110 | }
|
54 | 111 | }
|
| 112 | + if (changes.useProjectTemplate) { |
| 113 | + initializeSteps(); |
| 114 | + } |
55 | 115 | };
|
56 | 116 |
|
57 | 117 | $scope.$on('templateInstantiated', function(event, message) {
|
|
61 | 121 |
|
62 | 122 | ctrl.$onDestroy = function() {
|
63 | 123 | clearValidityWatcher();
|
| 124 | + if (projectListWatcher) { |
| 125 | + DataService.unwatch(projectListWatcher); |
| 126 | + } |
64 | 127 | };
|
65 | 128 |
|
66 | 129 | ctrl.next = function(step) {
|
|
85 | 148 | }
|
86 | 149 | };
|
87 | 150 |
|
| 151 | + ctrl.onProjectSelected = function(project) { |
| 152 | + ctrl.selectedProject = project; |
| 153 | + ctrl.configStep.valid = $scope.$ctrl.form.$valid && ctrl.selectedProject; |
| 154 | + }; |
| 155 | + |
| 156 | + ctrl.templateSelected = function(template) { |
| 157 | + ctrl.selectedTemplate = template; |
| 158 | + ctrl.template = _.get(template, 'resource'); |
| 159 | + ctrl.selectStep.valid = !!template; |
| 160 | + }; |
| 161 | + |
| 162 | + ctrl.templateProjectChange = function () { |
| 163 | + ctrl.templateProjectName = _.get(ctrl.templateProject, 'metadata.name'); |
| 164 | + |
| 165 | + // Get the templates for the selected project |
| 166 | + ctrl.catalogItems = {}; |
| 167 | + ctrl.templateSelected(); |
| 168 | + |
| 169 | + Catalog.getProjectCatalogItems(ctrl.templateProjectName).then( _.spread(function(catalogServiceItems, errorMessage) { |
| 170 | + ctrl.catalogItems = catalogServiceItems; |
| 171 | + ctrl.totalCount = ctrl.catalogItems.length; |
| 172 | + filterItems(); |
| 173 | + |
| 174 | + if (errorMessage) { |
| 175 | + NotificationsService.addNotification( |
| 176 | + { |
| 177 | + type: "error", |
| 178 | + message: errorMessage |
| 179 | + } |
| 180 | + ); |
| 181 | + } |
| 182 | + })); |
| 183 | + }; |
| 184 | + |
88 | 185 | function getIconClass() {
|
89 | 186 | var icon = _.get(ctrl, 'template.metadata.annotations.iconClass', 'fa fa-clone');
|
90 | 187 | return (icon.indexOf('icon-') !== -1) ? 'font-icon ' + icon : icon;
|
91 | 188 | }
|
92 | 189 |
|
93 | 190 | function initializeSteps() {
|
94 |
| - ctrl.steps = [ctrl.configStep, ctrl.resultsStep]; |
| 191 | + if (!ctrl.steps) { |
| 192 | + ctrl.steps = [ctrl.selectStep, ctrl.configStep, ctrl.resultsStep]; |
| 193 | + } |
95 | 194 | }
|
96 | 195 |
|
97 | 196 | function clearValidityWatcher() {
|
|
101 | 200 | }
|
102 | 201 | }
|
103 | 202 |
|
| 203 | + function showSelect() { |
| 204 | + ctrl.selectStep.selected = true; |
| 205 | + ctrl.configStep.selected = false; |
| 206 | + ctrl.resultsStep.selected = false; |
| 207 | + ctrl.nextTitle = "Next >"; |
| 208 | + clearValidityWatcher(); |
| 209 | + listProjects(); |
| 210 | + } |
| 211 | + |
104 | 212 | function showConfig() {
|
| 213 | + ctrl.selectStep.selected = false; |
105 | 214 | ctrl.configStep.selected = true;
|
106 | 215 | ctrl.resultsStep.selected = false;
|
107 | 216 | ctrl.nextTitle = "Create";
|
108 | 217 | ctrl.resultsStep.allowed = ctrl.configStep.valid;
|
109 | 218 |
|
110 | 219 | validityWatcher = $scope.$watch("$ctrl.form.$valid", function(isValid) {
|
111 |
| - ctrl.configStep.valid = isValid; |
| 220 | + ctrl.configStep.valid = isValid && ctrl.selectedProject; |
112 | 221 | ctrl.resultsStep.allowed = isValid;
|
113 | 222 | });
|
114 | 223 | }
|
115 | 224 |
|
116 | 225 | function showResults() {
|
| 226 | + ctrl.selectStep.selected = false; |
117 | 227 | ctrl.configStep.selected = false;
|
118 | 228 | ctrl.resultsStep.selected = true;
|
119 | 229 | ctrl.nextTitle = "Close";
|
|
124 | 234 | function instantiateTemplate() {
|
125 | 235 | $scope.$broadcast('instantiateTemplate');
|
126 | 236 | }
|
| 237 | + |
| 238 | + function filterForKeywords (searchText, items) { |
| 239 | + return KeywordService.filterForKeywords(items, ['name', 'tags'], KeywordService.generateKeywords(searchText)); |
| 240 | + } |
| 241 | + |
| 242 | + function filterChange (filters) { |
| 243 | + // only use filters which have a filter criteria 'value' |
| 244 | + // prevents applying an empty keyword filter |
| 245 | + // TODO: can remove the following line of code after angular-patternfly issue is fixed: |
| 246 | + // https://github.com/patternfly/angular-patternfly/issues/509 |
| 247 | + filters = _.filter(filters, 'value'); |
| 248 | + |
| 249 | + ctrl.filterConfig.appliedFilters = filters; |
| 250 | + filterItems(); |
| 251 | + } |
| 252 | + |
| 253 | + function filterItems() { |
| 254 | + ctrl.filteredItems = ctrl.catalogItems; |
| 255 | + if (ctrl.filterConfig.appliedFilters && ctrl.filterConfig.appliedFilters.length > 0) { |
| 256 | + _.each(ctrl.filterConfig.appliedFilters, function(filter) { |
| 257 | + ctrl.filteredItems = filterForKeywords(filter.value, ctrl.filteredItems); |
| 258 | + }); |
| 259 | + } |
| 260 | + |
| 261 | + updateFilterControls(); |
| 262 | + |
| 263 | + // Deselect the currently selected template if it was filtered out |
| 264 | + if (!_.includes(ctrl.filteredItems, ctrl.selectedTemplate)) { |
| 265 | + ctrl.templateSelected(); |
| 266 | + } |
| 267 | + } |
| 268 | + |
| 269 | + function updateFilterControls() { |
| 270 | + $timeout(function() { |
| 271 | + if (ctrl.filterConfig.appliedFilters.length > 0) { |
| 272 | + ctrl.filterConfig.resultsCount = ctrl.filteredItems.length; |
| 273 | + $('.toolbar-pf-results h5').text(ctrl.filterConfig.resultsCount + ' of ' + ctrl.totalCount + ' items'); |
| 274 | + } else { |
| 275 | + $('.toolbar-pf-results h5').text(ctrl.totalCount + (ctrl.totalCount === 1 ? ' item' : ' items')); |
| 276 | + if (ctrl.totalCount <= 1) { |
| 277 | + $('.filter-pf.filter-fields input').attr('disabled', ''); |
| 278 | + } else { |
| 279 | + $('.filter-pf.filter-fields input').removeAttr("disabled"); |
| 280 | + } |
| 281 | + } |
| 282 | + }, 0); |
| 283 | + } |
| 284 | + |
| 285 | + var updateProjects = function() { |
| 286 | + var filteredProjects = _.reject(ctrl.unfilteredProjects, 'metadata.deletionTimestamp'); |
| 287 | + var projects = _.sortBy(filteredProjects, $filter('displayName')); |
| 288 | + ctrl.searchEnabled = !_.isEmpty(filteredProjects); |
| 289 | + |
| 290 | + ctrl.templateProjects = RecentlyViewedProjectsService.orderByMostRecentlyViewed(projects); |
| 291 | + }; |
| 292 | + |
| 293 | + var updateProjectData = function(projectData) { |
| 294 | + ctrl.unfilteredProjects = _.toArray(projectData.by("metadata.name")); |
| 295 | + updateProjects(); |
| 296 | + }; |
| 297 | + |
| 298 | + function listProjects() { |
| 299 | + if (!projectListWatcher) { |
| 300 | + ProjectsService.list().then(function(projectData) { |
| 301 | + $scope.isProjectListIncomplete = ProjectsService.isProjectListIncomplete(); |
| 302 | + updateProjectData(projectData); |
| 303 | + |
| 304 | + if (!$scope.isProjectListIncomplete && _.size(ctrl.unfilteredProjects) <= MAX_PROJECTS_TO_WATCH) { |
| 305 | + projectListWatcher = ProjectsService.watch($scope, updateProjectData); |
| 306 | + } |
| 307 | + }, function() { |
| 308 | + $scope.isProjectListIncomplete = true; |
| 309 | + ctrl.unfilteredProjects = []; |
| 310 | + updateProjects(); |
| 311 | + }); |
| 312 | + } |
| 313 | + } |
127 | 314 | }
|
128 | 315 | })();
|
0 commit comments