/** * An element which displays a linear workflow of sections, each completed in order before the next * step is made visible. */ angular.module('quay').directive('linearWorkflow', function () { var directiveDefinitionObject = { priority: 0, templateUrl: '/static/directives/linear-workflow.html', replace: false, transclude: true, restrict: 'C', scope: { 'workflowState': '=?workflowState', 'workflowComplete': '&workflowComplete', 'doneTitle': '@doneTitle' }, controller: function($scope, $element, $timeout) { $scope.sections = []; $scope.nextSection = function() { if (!$scope.currentSection.valid) { return; } var currentIndex = $scope.currentSection.index; if (currentIndex + 1 >= $scope.sections.length) { $scope.workflowComplete(); return; } $scope.workflowState = $scope.sections[currentIndex + 1].id; }; this.registerSection = function(sectionScope, sectionElement) { // Add the section to the list. var sectionInfo = { 'index': $scope.sections.length, 'id': sectionScope.sectionId, 'title': sectionScope.sectionTitle, 'scope': sectionScope, 'element': sectionElement }; $scope.sections.push(sectionInfo); // Add a watch on the `sectionValid` value on the section itself. If/when this value // changes, we copy it over to the sectionInfo, so that the overall workflow can watch // the change. sectionScope.$watch('sectionValid', function(isValid) { sectionInfo['valid'] = isValid; if (!isValid) { // Reset the sections back to this section. updateState(); } }); // Bind the `submitSection` callback to move to the next section when the user hits // enter (which calls this method on the scope via an ng-submit set on a wrapping //
tag). sectionScope.submitSection = function() { $scope.nextSection(); }; // Update the state of the workflow to account for the new section. updateState(); }; var updateState = function() { // Find the furthest state we can show. var foundIndex = 0; var maxValidIndex = -1; $scope.sections.forEach(function(section, index) { if (section.id == $scope.workflowState) { foundIndex = index; } if (maxValidIndex == index - 1 && section.valid) { maxValidIndex = index; } }); var minSectionIndex = Math.min(maxValidIndex + 1, foundIndex); $scope.sections.forEach(function(section, index) { section.scope.sectionVisible = index <= minSectionIndex; section.scope.isCurrentSection = false; }); $scope.workflowState = null; if (minSectionIndex >= 0 && minSectionIndex < $scope.sections.length) { $scope.currentSection = $scope.sections[minSectionIndex]; $scope.workflowState = $scope.currentSection.id; $scope.currentSection.scope.isCurrentSection = true; // Focus to the first input (if any) in the section. $timeout(function() { var inputs = $scope.currentSection.element.find('input'); if (inputs.length == 1) { inputs.focus(); } }, 10); } }; $scope.$watch('workflowState', updateState); } }; return directiveDefinitionObject; }); /** * An element which displays a single section in a linear workflow. */ angular.module('quay').directive('linearWorkflowSection', function () { var directiveDefinitionObject = { priority: 0, templateUrl: '/static/directives/linear-workflow-section.html', replace: false, transclude: true, restrict: 'C', require: '^linearWorkflow', scope: { 'sectionId': '@sectionId', 'sectionTitle': '@sectionTitle', 'sectionValid': '=?sectionValid', }, link: function($scope, $element, $attrs, $ctrl) { $ctrl.registerSection($scope, $element); }, controller: function($scope, $element) { $scope.$watch('sectionVisible', function(visible) { if (visible) { $element.show(); } else { $element.hide(); } }); } }; return directiveDefinitionObject; });