Skip to content

Commit bf5d640

Browse files
committed
Support creating templates in a dialog
1 parent 568b56c commit bf5d640

14 files changed

+368
-119
lines changed

app/index.html

+2-1
Original file line numberDiff line numberDiff line change
@@ -282,7 +282,7 @@ <h1>JavaScript Required</h1>
282282
<script src="scripts/controllers/modals/deleteModal.js"></script>
283283
<script src="scripts/controllers/modals/debugTerminal.js"></script>
284284
<script src="scripts/controllers/modals/confirmReplaceModal.js"></script>
285-
<script src="scripts/controllers/modals/processTemplateModal.js"></script>
285+
<script src="scripts/controllers/modals/processOrSaveTemplateModal.js"></script>
286286
<script src="scripts/controllers/modals/linkService.js"></script>
287287
<script src="scripts/controllers/modals/jenkinsfileExamplesModal.js"></script>
288288
<script src="scripts/controllers/modals/aboutComputeUnitsModal.js"></script>
@@ -345,6 +345,7 @@ <h1>JavaScript Required</h1>
345345
<script src="scripts/directives/routeServiceBarChart.js"></script>
346346
<script src="scripts/directives/bindService.js"></script>
347347
<script src="scripts/directives/processTemplate.js"></script>
348+
<script src="scripts/directives/processTemplateDialog.js"></script>
348349
<script src="scripts/directives/create/nextSteps.js"></script>
349350

350351
<!-- Old Overview, TODO: remove -->

app/scripts/controllers/landingPage.js

+9-1
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,16 @@ angular.module('openshiftConsole')
1818
// Once all pages show notifications this should be removed.
1919
NotificationsService.clearNotifications();
2020

21+
$scope.templateSelected = function(template) {
22+
$scope.template = template;
23+
};
24+
25+
$scope.templateDialogClosed = function() {
26+
$scope.template = null;
27+
};
28+
2129
AuthService.withUser().then(function() {
22-
Catalog.getCatalogItems().then(function(items) {
30+
Catalog.getCatalogItems(true).then(function(items) {
2331
$scope.catalogItems = items;
2432
});
2533
});

app/scripts/controllers/modals/processTemplateModal.js renamed to app/scripts/controllers/modals/processOrSaveTemplateModal.js

+3-3
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,13 @@
22

33
/**
44
* @ngdoc function
5-
* @name openshiftConsole.controller:ProcessTemplateModalController
5+
* @name openshiftConsole.controller:ProcessOrSaveTemplateModalController
66
* @description
7-
* # ProcessTemplateModalController
7+
* # ProcessOrSaveTemplateModalController
88
* Controller of the openshiftConsole
99
*/
1010
angular.module('openshiftConsole')
11-
.controller('ProcessTemplateModalController', function ($scope, $uibModalInstance) {
11+
.controller('ProcessOrSaveTemplateModalController', function ($scope, $uibModalInstance) {
1212
$scope.continue = function() {
1313
$uibModalInstance.close('create');
1414
};

app/scripts/directives/fromFile.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -216,8 +216,8 @@ angular.module("openshiftConsole")
216216
function openTemplateProcessModal() {
217217
var modalInstance = $uibModal.open({
218218
animation: true,
219-
templateUrl: 'views/modals/process-template.html',
220-
controller: 'ProcessTemplateModalController',
219+
templateUrl: 'views/modals/process-or-save-template.html',
220+
controller: 'ProcessOrSaveTemplateModalController',
221221
scope: $scope
222222
});
223223
modalInstance.result.then(function() {

app/scripts/directives/processTemplate.js

+95-38
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,9 @@ angular.module('openshiftConsole').component('processTemplate', {
2121
template: '<',
2222
project: '<',
2323
alerts: '<',
24-
prefillParameters: '<'
24+
prefillParameters: '<',
25+
isDialog: '<',
26+
onProjectSelected: '&'
2527
},
2628
templateUrl: 'views/directives/process-template.html'
2729
});
@@ -41,7 +43,6 @@ function ProcessTemplate($filter,
4143
var ctrl = this;
4244

4345
var context;
44-
var projectDisplayName;
4546

4647
var dcContainers = $parse('spec.template.spec.containers');
4748
var builderImage = $parse('spec.strategy.sourceStrategy.from || spec.strategy.dockerStrategy.from || spec.strategy.customStrategy.from');
@@ -129,16 +130,17 @@ function ProcessTemplate($filter,
129130
images = [];
130131
var dcImages = [];
131132
var outputImages = {};
133+
var namespace = _.get(ctrl, 'selectedProject.metadata.name');
132134
angular.forEach(data.objects, function(item) {
133135
if (item.kind === "BuildConfig") {
134-
var builder = imageObjectRef(builderImage(item), ctrl.project.metadata.name);
136+
var builder = imageObjectRef(builderImage(item), namespace);
135137
if(builder) {
136138
images.push({
137139
name: builder,
138140
usesParameters: getParametersInImage(builder)
139141
});
140142
}
141-
var output = imageObjectRef(outputImage(item), ctrl.project.metadata.name);
143+
var output = imageObjectRef(outputImage(item), namespace);
142144
if (output) {
143145
outputImages[output] = true;
144146
}
@@ -185,23 +187,29 @@ function ProcessTemplate($filter,
185187
ctrl.$onInit = function() {
186188
ctrl.labels = [];
187189
ctrl.templateDisplayName = displayName(ctrl.template);
188-
context = {
189-
namespace: ctrl.project.metadata.name
190-
};
191-
projectDisplayName = displayName(ctrl.project);
190+
ctrl.selectedProject = ctrl.project;
192191
setTemplateParams();
193192
};
194193

194+
$scope.$watch(function() {
195+
return ctrl.selectedProject;
196+
}, function(project) {
197+
var cb = ctrl.onProjectSelected();
198+
if (cb) {
199+
cb(project);
200+
}
201+
});
202+
195203
var processedResources;
196204
var createResources = function() {
197205
var titles = {
198-
started: "Creating " + ctrl.templateDisplayName + " in project " + projectDisplayName,
199-
success: "Created " + ctrl.templateDisplayName + " in project " + projectDisplayName,
200-
failure: "Failed to create " + ctrl.templateDisplayName + " in project " + projectDisplayName
206+
started: "Creating " + ctrl.templateDisplayName + " in project " + displayName(ctrl.selectedProject),
207+
success: "Created " + ctrl.templateDisplayName + " in project " + displayName(ctrl.selectedProject),
208+
failure: "Failed to create " + ctrl.templateDisplayName + " in project " + displayName(ctrl.selectedProject)
201209
};
202210
var helpLinks = getHelpLinks(ctrl.template);
203211
TaskList.clear();
204-
TaskList.add(titles, helpLinks, ctrl.project.metadata.name, function() {
212+
TaskList.add(titles, helpLinks, ctrl.selectedProject.metadata.name, function() {
205213
var d = $q.defer();
206214
DataService.batch(processedResources, context).then(
207215
function(result) {
@@ -235,7 +243,15 @@ function ProcessTemplate($filter,
235243
);
236244
return d.promise;
237245
});
238-
Navigate.toNextSteps(ctrl.templateDisplayName, ctrl.project.metadata.name);
246+
247+
if (ctrl.isDialog) {
248+
$scope.$emit('templateInstantiated', {
249+
project: ctrl.selectedProject,
250+
template: ctrl.template
251+
});
252+
} else {
253+
Navigate.toNextSteps(ctrl.templateDisplayName, ctrl.selectedProject.metadata.name);
254+
}
239255
};
240256

241257
var launchConfirmationDialog = function(alerts) {
@@ -260,7 +276,7 @@ function ProcessTemplate($filter,
260276
};
261277

262278
var showWarningsOrCreate = function(result) {
263-
var alerts = SecurityCheckService.getSecurityAlerts(processedResources, ctrl.project.metadata.name);
279+
var alerts = SecurityCheckService.getSecurityAlerts(processedResources, ctrl.selectedProject.metadata.name);
264280

265281
// Now that all checks are completed, show any Alerts if we need to
266282
var quotaAlerts = result.quotaAlerts || [];
@@ -279,36 +295,77 @@ function ProcessTemplate($filter,
279295
}
280296
};
281297

282-
ctrl.createFromTemplate = function() {
283-
ctrl.disableInputs = true;
284-
var userLabels = keyValueEditorUtils.mapEntries(keyValueEditorUtils.compactEntries(ctrl.labels));
285-
var systemLabels = keyValueEditorUtils.mapEntries(keyValueEditorUtils.compactEntries(ctrl.systemLabels));
286-
ctrl.template.labels = _.extend(systemLabels, userLabels);
287-
288-
DataService.create("processedtemplates", null, ctrl.template, context).then(
289-
function(config) { // success
290-
// Cache template parameters and message so they can be displayed in the nexSteps page
291-
ProcessedTemplateService.setTemplateData(config.parameters, ctrl.template.parameters, config.message);
292-
processedResources = config.objects;
298+
var createProjectIfNecessary = function() {
299+
if (_.has(ctrl.selectedProject, 'metadata.uid')) {
300+
return $q.when();
301+
}
293302

294-
QuotaService.getLatestQuotaAlerts(processedResources, context).then(showWarningsOrCreate);
303+
var newProjName = ctrl.selectedProject.metadata.name;
304+
var newProjDisplayName = ctrl.selectedProject.metadata.annotations['new-display-name'];
305+
var newProjDesc = $filter('description')(ctrl.selectedProject);
306+
var projReqObj = {
307+
apiVersion: "v1",
308+
kind: "ProjectRequest",
309+
metadata: {
310+
name: newProjName
295311
},
296-
function(result) { // failure
297-
ctrl.disableInputs = false;
298-
var details;
299-
if (result.data && result.data.message) {
300-
details = result.data.message;
312+
displayName: newProjDisplayName,
313+
description: newProjDesc
314+
};
315+
return DataService.create('projectrequests', null, projReqObj, $scope);
316+
};
317+
318+
ctrl.createFromTemplate = function() {
319+
ctrl.disableInputs = true;
320+
createProjectIfNecessary().then(function() {
321+
context = {
322+
namespace: ctrl.selectedProject.metadata.name
323+
};
324+
var userLabels = keyValueEditorUtils.mapEntries(keyValueEditorUtils.compactEntries(ctrl.labels));
325+
var systemLabels = keyValueEditorUtils.mapEntries(keyValueEditorUtils.compactEntries(ctrl.systemLabels));
326+
ctrl.template.labels = _.extend(systemLabels, userLabels);
327+
328+
DataService.create("processedtemplates", null, ctrl.template, context).then(
329+
function(config) { // success
330+
// Cache template parameters and message so they can be displayed in the nexSteps page
331+
ProcessedTemplateService.setTemplateData(config.parameters, ctrl.template.parameters, config.message);
332+
processedResources = config.objects;
333+
334+
QuotaService.getLatestQuotaAlerts(processedResources, context).then(showWarningsOrCreate);
335+
},
336+
function(result) { // failure
337+
ctrl.disableInputs = false;
338+
var details;
339+
if (result.data && result.data.message) {
340+
details = result.data.message;
341+
}
342+
ctrl.alerts["process"] =
343+
{
344+
type: "error",
345+
message: "An error occurred processing the template.",
346+
details: details
347+
};
301348
}
302-
ctrl.alerts["process"] =
303-
{
304-
type: "error",
305-
message: "An error occurred processing the template.",
306-
details: details
307-
};
349+
);
350+
}, function(result) {
351+
ctrl.disableInputs = false;
352+
var details;
353+
if (result.data && result.data.message) {
354+
details = result.data.message;
308355
}
309-
);
356+
ctrl.alerts["create-project"] = {
357+
type: "error",
358+
message: "An error occurred creating the project.",
359+
details: details
360+
};
361+
});
310362
};
311363

364+
// When the process-template component is displayed in a dialog, the create
365+
// button is outside the component since it is in the wizard footer. Listen
366+
// for an event for when the button is clicked.
367+
$scope.$on('instantiateTemplate', ctrl.createFromTemplate);
368+
312369
var shouldAddAppLabel = function() {
313370
// If the template defines its own app label, we don't need to add one at all
314371
if (_.get(ctrl.template, 'labels.app')) {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
'use strict';
2+
3+
angular.module('openshiftConsole').component('processTemplateDialog', {
4+
controller: [
5+
'$scope',
6+
'DataService',
7+
ProcessTemplateDialog
8+
],
9+
controllerAs: '$ctrl',
10+
bindings: {
11+
template: '<',
12+
onDialogClosed: '&'
13+
},
14+
templateUrl: 'views/directives/process-template-dialog.html'
15+
});
16+
17+
function ProcessTemplateDialog($scope, DataService) {
18+
var ctrl = this;
19+
20+
var initializeSteps = function() {
21+
ctrl.steps = [{
22+
id: 'configuration',
23+
label: 'Configuration',
24+
selected: true,
25+
visited: true
26+
}, {
27+
id: 'results',
28+
label: 'Results'
29+
}];
30+
ctrl.currentStep = ctrl.steps[0];
31+
};
32+
33+
ctrl.$onInit = function() {
34+
ctrl.alerts = {};
35+
ctrl.loginBaseUrl = DataService.openshiftAPIBaseUrl();
36+
};
37+
38+
var getIconClass = function() {
39+
var icon = _.get(ctrl, 'template.metadata.annotations.iconClass', 'fa fa-cubes');
40+
return (icon.indexOf('icon-') !== -1) ? 'font-icon ' + icon : icon;
41+
};
42+
43+
ctrl.$onChanges = function(changes) {
44+
if (changes.template) {
45+
initializeSteps();
46+
ctrl.iconClass = getIconClass();
47+
}
48+
};
49+
50+
var showResults = function() {
51+
ctrl.steps[0].selected = false;
52+
ctrl.currentStep = ctrl.steps[1];
53+
ctrl.currentStep.selected = true;
54+
ctrl.currentStep.visited = true;
55+
};
56+
57+
ctrl.instantiateTemplate = function() {
58+
$scope.$broadcast('instantiateTemplate');
59+
};
60+
61+
$scope.$on('templateInstantiated', function(result) {
62+
$scope.selectedProject = result.project;
63+
showResults();
64+
});
65+
66+
ctrl.close = function() {
67+
var cb = ctrl.onDialogClosed();
68+
if (cb) {
69+
cb();
70+
}
71+
};
72+
}

app/scripts/directives/templateopt.js

+14-1
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,12 @@ angular.module('openshiftConsole')
66
return {
77
restrict: 'E',
88
templateUrl: 'views/_templateopt.html',
9+
transclude: true,
910
scope: {
1011
parameters: "=",
1112
expand: "=?",
12-
canToggle: "=?"
13+
canToggle: "=?",
14+
isDialog: "=?"
1315
},
1416
link: function(scope, element, attrs) {
1517
if (!angular.isDefined(attrs.canToggle)) {
@@ -23,6 +25,17 @@ angular.module('openshiftConsole')
2325
scope.focus = function(id) {
2426
angular.element('#' + id).focus();
2527
};
28+
29+
if (!scope.isDialog) {
30+
scope.visibleParameters = scope.parameters;
31+
} else {
32+
scope.$watch('parameters', function(parameters) {
33+
// Only show parameters that the user has to fill in a value when in a dialog.
34+
scope.visibleParameters = _.reject(parameters, function(parameter) {
35+
return !parameter.required || parameter.value || parameter.generate;
36+
});
37+
});
38+
}
2639
}
2740
};
2841
});

app/styles/_core.less

+5-6
Original file line numberDiff line numberDiff line change
@@ -597,8 +597,6 @@ label.checkbox {
597597
}
598598
}
599599
.form-group {
600-
width: 100%;
601-
602600
.parameter-input-wrapper {
603601
position: relative;
604602

@@ -611,10 +609,11 @@ label.checkbox {
611609
transform: rotate(90deg);
612610
}
613611
}
614-
615-
input, textarea {
616-
padding-right: 20px;
617-
}
612+
}
613+
}
614+
&.form-horizontal .form-group .parameter-input-wrapper {
615+
.resize-input {
616+
right: 26px;
618617
}
619618
}
620619
.help-block {

0 commit comments

Comments
 (0)