Skip to content

Commit 873fd72

Browse files
authored
Merge pull request #458 from jeff-phillips-18/wizard
Wizard Enhancements
2 parents 8d07d3f + d5217bd commit 873fd72

16 files changed

+331
-74
lines changed

misc/examples.css

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,3 +130,14 @@ hr {
130130
.dropdown-kebab-pf.red .btn-link {
131131
color: red;
132132
}
133+
134+
.example-wizard-sidebar {
135+
height: 500px;
136+
max-height: 500px;
137+
overflow-y: auto;
138+
}
139+
.example-wizard-step {
140+
height: 500px;
141+
max-height: 500px;
142+
overflow-y: auto;
143+
}

src/wizard/wizard-buttons.js

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,32 @@
55
.directive(action, function () {
66
return {
77
restrict: 'A',
8-
require: '^pf-wizard',
98
scope: {
109
callback: "=?"
1110
},
12-
link: function ($scope, $element, $attrs, wizard) {
11+
controller: function ($scope) {
12+
var findWizard = function (scope) {
13+
var wizard;
14+
15+
if (scope) {
16+
if (angular.isDefined(scope.wizard)) {
17+
wizard = scope.wizard;
18+
} else {
19+
wizard = findWizard(scope.$parent);
20+
}
21+
}
22+
23+
return wizard;
24+
};
25+
$scope.wizard = findWizard($scope);
26+
},
27+
link: function ($scope, $element, $attrs) {
1328
$element.on("click", function (e) {
1429
e.preventDefault();
1530
$scope.$apply(function () {
1631
// scope apply in button module
1732
$scope.$eval($attrs[action]);
18-
wizard[action.replace("pfWiz", "").toLowerCase()]($scope.callback);
33+
$scope.wizard[action.replace("pfWiz", "").toLowerCase()]($scope.callback);
1934
});
2035
});
2136
}

src/wizard/wizard-directive.js

Lines changed: 62 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,12 @@
2020
*
2121
* @param {string} title The wizard title displayed in the header
2222
* @param {boolean=} hideIndicators Hides the step indicators in the header of the wizard
23+
* @param {boolean=} hideSidebar Hides page navigation sidebar on the wizard pages
24+
* @param {boolean=} hideHeader Optional value to hide the title bar. Default is false.
25+
* @param {boolean=} hideBackButton Optional value to hide the back button, useful in 2 step wizards. Default is false.
26+
* @param {string=} stepClass Optional CSS class to be given to the steps page container. Used for the sidebar panel as well unless a sidebarClass is provided.
27+
* @param {string=} sidebarClass Optional CSS class to be give to the sidebar panel. Only used if the stepClass is also provided.
28+
* @param {string=} contentHeight The height the wizard content should be set to. This is used ONLY if the stepClass is not given. This defaults to 300px if the property is not supplied.
2329
* @param {string=} currentStep The current step can be changed externally - this is the title of the step to switch the wizard to
2430
* @param {string=} cancelTitle The text to display on the cancel button
2531
* @param {string=} backTitle The text to display on the back button
@@ -32,7 +38,6 @@
3238
* @param {boolean=} wizardDone Value that is set when the wizard is done
3339
* @param {string} loadingWizardTitle The text displayed when the wizard is loading
3440
* @param {string=} loadingSecondaryInformation Secondary descriptive information to display when the wizard is loading
35-
* @param {string=} contentHeight The height the wizard content should be set to. This defaults to 300px if the property is not supplied.
3641
* @param {boolean=} embedInPage Value that indicates wizard is embedded in a page (not a modal). This moves the navigation buttons to the left hand side of the footer and removes the close button.
3742
*
3843
* @example
@@ -51,7 +56,8 @@
5156
next-callback="nextCallback"
5257
back-callback="backCallback"
5358
wizard-done="deployComplete || deployInProgress"
54-
content-height="'600px'"
59+
sidebar-class="example-wizard-sidebar"
60+
step-class="example-wizard-step"
5561
loading-secondary-information="secondaryLoadInformation">
5662
<div pf-wizard-step step-title="First Step" substeps="true" step-id="details" step-priority="0" show-review="true" show-review-details="true">
5763
<div ng-include="'detail-page.html'">
@@ -305,6 +311,12 @@ angular.module('patternfly.wizard').directive('pfWizard', function ($window) {
305311
scope: {
306312
title: '@',
307313
hideIndicators: '=?',
314+
hideSidebar: '@',
315+
hideHeader: '@',
316+
hideBackButton: '@',
317+
sidebarClass: '@',
318+
stepClass: '@',
319+
contentHeight: '=?',
308320
currentStep: '=?',
309321
cancelTitle: '=?',
310322
backTitle: '=?',
@@ -317,7 +329,6 @@ angular.module('patternfly.wizard').directive('pfWizard', function ($window) {
317329
wizardDone: '=?',
318330
loadingWizardTitle: '=?',
319331
loadingSecondaryInformation: '=?',
320-
contentHeight: '=?',
321332
embedInPage: '=?'
322333
},
323334
templateUrl: 'wizard/wizard.html',
@@ -388,21 +399,37 @@ angular.module('patternfly.wizard').directive('pfWizard', function ($window) {
388399
$scope.steps = [];
389400
$scope.context = {};
390401
this.context = $scope.context;
402+
$scope.hideHeader = $scope.hideHeader === 'true';
403+
this.hideSidebar = $scope.hideSidebar === 'true';
404+
$scope.hideBaackButton = $scope.hideBackButton === 'true';
391405

392-
if (angular.isUndefined($scope.wizardReady)) {
393-
$scope.wizardReady = true;
406+
// If a step class is given use it for all steps
407+
if (angular.isDefined($scope.stepClass)) {
408+
this.stepClass = $scope.stepClass;
409+
410+
// If a sidebarClass is given, us it for sidebar panel, if not, apply the stepsClass to the sidebar panel
411+
if (angular.isDefined($scope.sidebarClass)) {
412+
this.sidebarClass = $scope.sidebarClass;
413+
} else {
414+
this.sidebarClass = $scope.stepClass;
415+
}
416+
} else {
417+
// No step claass give, setup the content style to allow scrolling and a fixed height
418+
if (angular.isUndefined($scope.contentHeight)) {
419+
$scope.contentHeight = '300px';
420+
}
421+
this.contentHeight = $scope.contentHeight;
422+
$scope.contentStyle = {
423+
'height': $scope.contentHeight,
424+
'max-height': $scope.contentHeight,
425+
'overflow-y': 'auto'
426+
};
427+
this.contentStyle = $scope.contentStyle;
394428
}
395429

396-
if (angular.isUndefined($scope.contentHeight)) {
397-
$scope.contentHeight = '300px';
430+
if (angular.isUndefined($scope.wizardReady)) {
431+
$scope.wizardReady = true;
398432
}
399-
this.contentHeight = $scope.contentHeight;
400-
$scope.contentStyle = {
401-
'height': $scope.contentHeight,
402-
'max-height': $scope.contentHeight,
403-
'overflow-y': 'auto'
404-
};
405-
this.contentStyle = $scope.contentStyle;
406433

407434
$scope.nextEnabled = false;
408435
$scope.prevEnabled = false;
@@ -513,6 +540,14 @@ angular.module('patternfly.wizard').directive('pfWizard', function ($window) {
513540
}
514541
};
515542

543+
$scope.allowStepIndicatorClick = function (step) {
544+
return step.allowClickNav &&
545+
!$scope.wizardDone &&
546+
$scope.selectedStep.okToNavAway &&
547+
($scope.selectedStep.nextEnabled || (step.stepPriority < $scope.selectedStep.stepPriority)) &&
548+
($scope.selectedStep.prevEnabled || (step.stepPriority > $scope.selectedStep.stepPriority));
549+
};
550+
516551
$scope.stepClick = function (step) {
517552
if (step.allowClickNav) {
518553
$scope.goTo(step, true);
@@ -602,13 +637,14 @@ angular.module('patternfly.wizard').directive('pfWizard', function ($window) {
602637
// Check if callback is a function
603638
if (angular.isFunction(callback)) {
604639
if (callback($scope.selectedStep)) {
605-
if (index === enabledSteps.length - 1) {
606-
this.finish();
607-
} else {
640+
if (index <= enabledSteps.length - 1) {
608641
// Go to the next step
609642
if (enabledSteps[index + 1].substeps) {
610643
enabledSteps[index + 1].resetNav();
611644
}
645+
} else {
646+
this.finish();
647+
return;
612648
}
613649
} else {
614650
return;
@@ -645,6 +681,12 @@ angular.module('patternfly.wizard').directive('pfWizard', function ($window) {
645681
$scope.goTo($scope.getEnabledSteps()[index - 1]);
646682
}
647683
}
684+
} else {
685+
if (index === 0) {
686+
throw new Error("Can't go back. It's already in step 0");
687+
} else {
688+
$scope.goTo($scope.getEnabledSteps()[index - 1]);
689+
}
648690
}
649691
};
650692

@@ -673,6 +715,9 @@ angular.module('patternfly.wizard').directive('pfWizard', function ($window) {
673715
//go to first step
674716
this.goTo(0);
675717
};
718+
719+
// Provide wizard controls to steps and sub-steps
720+
$scope.wizard = this;
676721
},
677722
link: function ($scope) {
678723
$scope.$watch('wizardReady', function () {

src/wizard/wizard-review-page-directive.js

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,23 @@ angular.module('patternfly.wizard').directive('pfWizardReviewPage', function ()
1717
shown: '=',
1818
wizardData: "="
1919
},
20-
require: '^pf-wizard',
2120
templateUrl: 'wizard/wizard-review-page.html',
2221
controller: function ($scope) {
22+
var findWizard = function (scope) {
23+
var wizard;
24+
if (scope) {
25+
if (angular.isDefined(scope.wizard)) {
26+
wizard = scope.wizard;
27+
} else {
28+
wizard = findWizard(scope.$parent);
29+
}
30+
}
31+
32+
return wizard;
33+
};
34+
35+
$scope.wizard = findWizard($scope.$parent);
36+
2337
$scope.toggleShowReviewDetails = function (step) {
2438
if (step.showReviewDetails === true) {
2539
step.showReviewDetails = false;
@@ -38,10 +52,10 @@ angular.module('patternfly.wizard').directive('pfWizardReviewPage', function ()
3852
$scope.reviewSteps = wizard.getReviewSteps();
3953
};
4054
},
41-
link: function ($scope, $element, $attrs, wizard) {
55+
link: function ($scope, $element, $attrs) {
4256
$scope.$watch('shown', function (value) {
4357
if (value) {
44-
$scope.updateReviewSteps(wizard);
58+
$scope.updateReviewSteps($scope.wizard);
4559
}
4660
});
4761
}

src/wizard/wizard-step-directive.js

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,6 @@ angular.module('patternfly.wizard').directive('pfWizardStep', function () {
4747
showReviewDetails: '@?',
4848
reviewTemplate: '@?'
4949
},
50-
require: '^pf-wizard',
5150
templateUrl: 'wizard/wizard-step.html',
5251
controller: function ($scope, $timeout) {
5352
var firstRun = true;
@@ -113,8 +112,23 @@ angular.module('patternfly.wizard').directive('pfWizardStep', function () {
113112
return foundStep;
114113
};
115114

115+
var findWizard = function (scope) {
116+
var wizard;
117+
if (scope) {
118+
if (angular.isDefined(scope.wizard)) {
119+
wizard = scope.wizard;
120+
} else {
121+
wizard = findWizard(scope.$parent);
122+
}
123+
}
124+
125+
return wizard;
126+
};
127+
116128
$scope.steps = [];
117129
$scope.context = {};
130+
$scope.wizard = findWizard($scope.$parent);
131+
this.wizard = $scope.wizard;
118132
this.context = $scope.context;
119133

120134
if (angular.isUndefined($scope.nextEnabled)) {
@@ -328,6 +342,9 @@ angular.module('patternfly.wizard').directive('pfWizardStep', function () {
328342
$scope.goTo(stepTo);
329343
};
330344

345+
// Provide wizard step controls to sub-steps
346+
$scope.wizardStep = this;
347+
331348
// Method used for next button within step
332349
$scope.next = function (callback) {
333350
var enabledSteps = $scope.getEnabledSteps();
@@ -387,14 +404,13 @@ angular.module('patternfly.wizard').directive('pfWizardStep', function () {
387404
};
388405
}
389406
},
390-
link: function ($scope, $element, $attrs, wizard) {
407+
link: function ($scope, $element, $attrs) {
391408
$scope.$watch($attrs.ngShow, function (value) {
392-
$scope.pageNumber = wizard.getStepNumber($scope);
409+
$scope.pageNumber = $scope.wizard.getStepNumber($scope);
393410
});
394411
$scope.title = $scope.stepTitle;
395-
$scope.contentStyle = wizard.contentStyle;
396-
wizard.addStep($scope);
397-
$scope.wizard = wizard;
412+
$scope.contentStyle = $scope.wizard.contentStyle;
413+
$scope.wizard.addStep($scope);
398414
}
399415
};
400416
});

src/wizard/wizard-step.html

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<section ng-show="selected" ng-class="{current: selected, done: completed}">
2-
<div class="wizard-pf-sidebar" ng-style="contentStyle" ng-if="substeps === true">
2+
<div ng-if="!wizard.hideSidebar" class="wizard-pf-sidebar" ng-style="contentStyle" ng-class="wizard.sidebarClass" ng-if="substeps === true">
33
<ul class="list-group">
44
<li class="list-group-item" ng-class="{active: step.selected}" ng-repeat="step in getEnabledSteps()">
55
<a ng-click="stepClick(step)">
@@ -9,7 +9,7 @@
99
</li>
1010
</ul>
1111
</div>
12-
<div class="wizard-pf-main" ng-class="{'wizard-pf-singlestep': !substeps}" ng-style="contentStyle">
12+
<div class="wizard-pf-main {{wizard.stepClass}}" ng-style="contentStyle" ng-class="{'wizard-pf-singlestep': !substeps || wizard.hideSidebar}">
1313
<div class="wizard-pf-contents" ng-transclude></div>
1414
</div>
1515
</section>

src/wizard/wizard-substep-directive.js

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,9 +39,24 @@ angular.module('patternfly.wizard').directive('pfWizardSubstep', function () {
3939
showReviewDetails: '@?',
4040
reviewTemplate: '@?'
4141
},
42-
require: '^pf-wizard-step',
4342
templateUrl: 'wizard/wizard-substep.html',
4443
controller: function ($scope) {
44+
var findWizardStep = function (scope) {
45+
var wizardStep;
46+
47+
if (scope) {
48+
if (angular.isDefined(scope.wizardStep)) {
49+
wizardStep = scope.wizardStep;
50+
} else {
51+
wizardStep = findWizardStep(scope.$parent);
52+
}
53+
}
54+
55+
return wizardStep;
56+
};
57+
58+
$scope.wizardStep = findWizardStep($scope);
59+
4560
if (angular.isUndefined($scope.nextEnabled)) {
4661
$scope.nextEnabled = true;
4762
}
@@ -74,9 +89,9 @@ angular.module('patternfly.wizard').directive('pfWizardSubstep', function () {
7489
};
7590

7691
},
77-
link: function ($scope, $element, $attrs, step) {
92+
link: function ($scope, $element, $attrs) {
7893
$scope.title = $scope.stepTitle;
79-
step.addStep($scope);
94+
$scope.wizardStep.addStep($scope);
8095
}
8196
};
8297
});

src/wizard/wizard.html

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<div>
2-
<div class="modal-header">
2+
<div class="modal-header" ng-if="!hideHeader">
33
<button type="button" class="close wizard-pf-dismiss" aria-label="Close" ng-click="onCancel()" ng-if="!embedInPage">
44
<span aria-hidden="true">&times;</span>
55
</button>
@@ -10,7 +10,10 @@
1010
<div class="wizard-pf-steps" ng-class="{'invisible': !wizardReady}">
1111
<ul class="wizard-pf-steps-indicator" ng-if="!hideIndicators" ng-class="{'invisible': !wizardReady}">
1212
<li class="wizard-pf-step" ng-class="{active: step.selected}" ng-repeat="step in getEnabledSteps()" data-tabgroup="{{$index }}">
13-
<a ng-click="stepClick(step)"><span class="wizard-pf-step-number">{{$index + 1}}</span><span class="wizard-pf-step-title">{{step.title}}</span></a>
13+
<a ng-click="stepClick(step)" ng-class="{'disabled': !allowStepIndicatorClick(step)}">
14+
<span class="wizard-pf-step-number">{{$index + 1}}</span>
15+
<span class="wizard-pf-step-title">{{step.title}}</span>
16+
</a>
1417
</li>
1518
</ul>
1619
</div>
@@ -27,7 +30,7 @@ <h3 class="blank-slate-pf-main-action">{{loadingWizardTitle}}</h3>
2730
</div>
2831
<div class="modal-footer wizard-pf-footer wizard-pf-position-override" ng-class="{'wizard-pf-footer-inline': embedInPage}">
2932
<button pf-wiz-cancel class="btn btn-default btn-cancel wizard-pf-cancel" ng-disabled="wizardDone" ng-click="onCancel()" ng-if="!embedInPage">{{cancelTitle}}</button>
30-
<div class="tooltip-wrapper" uib-tooltip="{{prevTooltip}}" tooltip-placement="left">
33+
<div ng-if="!hideBackButton" class="tooltip-wrapper" uib-tooltip="{{prevTooltip}}" tooltip-placement="left">
3134
<button id="backButton" pf-wiz-previous class="btn btn-default" ng-disabled="!wizardReady || wizardDone || !prevEnabled || firstStep"
3235
callback="backCallback">
3336
<span class="i fa fa-angular-left"></span>

0 commit comments

Comments
 (0)