Start on work towards the tutorial. Note that this code is BROKEN

This commit is contained in:
Joseph Schorr 2014-02-05 21:00:04 -05:00
parent a049fc57c6
commit dbed1300ad
14 changed files with 338 additions and 63 deletions

View file

@ -771,6 +771,8 @@ quayApp = angular.module('quay', ['ngRoute', 'chieffancypants.loadingBar', 'angu
reloadOnSearch: false, controller: UserAdminCtrl}).
when('/guide/', {title: 'Guide', description:'Guide to using private docker repositories on Quay.io', templateUrl: '/static/partials/guide.html',
controller: GuideCtrl}).
when('/tutorial/', {title: 'Tutorial', description:'Interactive tutorial for using Quay.io', templateUrl: '/static/partials/tutorial.html',
controller: TutorialCtrl}).
when('/contact/', {title: 'Contact Us', description:'Different ways for you to get a hold of us when you need us most.', templateUrl: '/static/partials/contact.html',
controller: ContactCtrl}).
when('/plans/', {title: 'Plans and Pricing', description: 'Plans and pricing for private docker repositories on Quay.io',

View file

@ -42,35 +42,62 @@ function PlansCtrl($scope, $location, UserService, PlanService) {
};
}
function GuideCtrl($scope, AngularTour, AngularTourSignals) {
$scope.startTour = function() {
AngularTour.start({
'title': 'My Test Tour',
'steps': [
{
'title': 'Welcome to the tour!',
'content': 'Some cool content'
},
{
'title': 'A step tied to a DOM element',
'content': 'This is the best DOM element!',
'element': '#test-element'
},
{
'content': 'Waiting for the page to change',
'signal': AngularTourSignals.matchesLocation('/repository/')
},
{
'content': 'Waiting for the page to load',
'signal': AngularTourSignals.elementAvaliable('*[data-repo="public/publicrepo"]')
},
{
'content': 'Now click on the public repository',
'signal': AngularTourSignals.matchesLocation('/repository/public/publicrepo'),
'element': '*[data-repo="public/publicrepo"]'
function GuideCtrl($scope) {
}
function TutorialCtrl($scope, AngularTour, AngularTourSignals, UserService) {
$scope.tour = {
'title': 'Quay.io Tutorial',
'steps': [
{
'title': 'Welcome to the Quay.io tutorial!',
'templateUrl': '/static/tutorial/welcome.html'
},
{
'title': 'Sign in to get started',
'templateUrl': '/static/tutorial/signup.html',
'signal': function($tourScope) {
$tourScope.username = UserService.currentUser().username;
$tourScope.email = UserService.currentUser().email;
return !UserService.currentUser().anonymous;
}
]
});
},
{
'title': 'Step 1: Login to Quay.io',
'templateUrl': '/static/tutorial/docker-login.html',
'signal': AngularTourSignals.matchesLocation('/repository/'),
'waitMessage': "Waiting for login"
},
{
'title': 'Step 2: Create a new image',
'templateUrl': '/static/tutorial/create-image.html'
},
{
'title': 'Step 3: Push the image to Quay.io',
'templateUrl': '/static/tutorial/push-image.html'
},
{
'title': 'Step 4: View the repository on Quay.io',
'templateUrl': '/static/tutorial/view-repo.html',
'signal': AngularTourSignals.matchesLocation('/repository/'),
'waitMessage': "Waiting for image push to complete"
},
{
'content': 'Waiting for the page to load',
'signal': AngularTourSignals.elementAvaliable('*[data-repo="{{username}}/{{repoName}}"]'),
'overlayable': true
},
{
'content': 'Select your new repository from the list',
'signal': AngularTourSignals.matchesLocation('/repository/{{username}}/{{repoName}}'),
'element': '*[data-repo="{{username}}/{{repoName}}"]',
'overlayable': true
},
{
'content': 'And done!',
'overlayable': true
}
]
};
}

View file

@ -1,7 +1,11 @@
angular.module("angular-tour", [])
.provider('AngularTour', function() {
this.$get = ['$document', '$rootScope', '$compile', function($document, $rootScope, $compile) {
function _start(tour) {
this.$get = ['$document', '$rootScope', '$compile', '$location', function($document, $rootScope, $compile, $location) {
$rootScope.angular_tour_current = null;
function _start(tour, opt_stepIndex, opt_existingScope) {
tour.initialStep = opt_stepIndex || tour.initialStep || 0;
tour.tourScope = opt_existingScope || null;
$rootScope.angular_tour_current = tour;
}
@ -13,24 +17,53 @@ angular.module("angular-tour", [])
start: _start,
stop: _stop
};
}];
})
.directive('angularTourOverlay', function() {
.directive('angularTourUi', function() {
var directiveDefinitionObject = {
priority: 0,
templateUrl: '/static/directives/angular-tour-overlay.html',
templateUrl: '/static/directives/angular-tour-ui.html',
replace: false,
transclude: false,
restrict: 'C',
scope: {
'tour': '=tour'
'tour': '=tour',
'inline': '=inline',
},
controller: function($scope, $element, $interval) {
controller: function($rootScope, $scope, $element, $location, $interval, AngularTour) {
var createNewScope = function() {
var tourScope = {
'_replaceData': function(s) {
if (typeof s != 'string') {
return s;
}
for (var key in tourScope) {
if (key[0] == '_') { continue; }
if (tourScope.hasOwnProperty(key)) {
s = s.replace('{{' + key + '}}', tourScope[key]);
}
}
return s;
}
};
return tourScope;
};
$scope.stepIndex = 0;
$scope.step = null;
$scope.interval = null;
$scope.interval = null;
$scope.tourScope = createNewScope();
var getElement = function() {
if (typeof $scope.step['element'] == 'function') {
return $($scope.step['element'](tourScope));
}
return $($scope.tourScope._replaceData($scope.step['element']));
};
var checkSignalTimer = function() {
if (!$scope.step) {
@ -38,8 +71,8 @@ angular.module("angular-tour", [])
return;
}
var signal = $scope.step.signal;
if (signal()) {
var signal = $scope.step['signal'];
if (signal($scope.tourScope)) {
$scope.next();
}
};
@ -58,12 +91,12 @@ angular.module("angular-tour", [])
var closeDomHighlight = function() {
if (!$scope.step) { return; }
var element = $($scope.step.element);
var element = getElement($scope.tourScope);
element.spotlight('close');
};
var updateDomHighlight = function() {
var element = $($scope.step.element);
var element = getElement();
if (!element.length) {
return;
}
@ -94,6 +127,13 @@ angular.module("angular-tour", [])
}
$scope.step = $scope.tour.steps[stepIndex];
// If the signal is already true, then skip this step entirely.
if ($scope.step['signal'] && $scope.step['signal']($scope.tourScope)) {
$scope.setStepIndex(stepIndex + 1);
return;
}
$scope.stepIndex = stepIndex;
$scope.hasNextStep = stepIndex < $scope.tour.steps.length - 1;
@ -110,7 +150,9 @@ angular.module("angular-tour", [])
};
$scope.stop = function() {
closeDomHighlight();
$scope.tour = null;
AngularTour.stop();
};
$scope.next = function() {
@ -119,8 +161,35 @@ angular.module("angular-tour", [])
$scope.$watch('tour', function(tour) {
stopSignalTimer();
$scope.setStepIndex(0);
if (tour) {
$scope.setStepIndex(tour.initialStep || 0);
$scope.tourScope = tour.tourScope || createNewScope();
$scope.tour.tourScope = $scope.tourScope;
}
});
// If this is an inline tour, then we need to monitor the page to determine when
// to transition it to an overlay tour.
if ($scope.inline) {
var counter = 0;
var unbind = $rootScope.$watch(function() {
return $location.path();
}, function(location) {
// Since this callback fires for the first page display, we only unbind it
// after the second call.
if (counter == 1) {
// Unbind the listener.
unbind();
// If there is an active tour, transition it over to the overlay.
if ($scope.tour && $scope.step && $scope.step['overlayable']) {
AngularTour.start($scope.tour, $scope.stepIndex, $scope.tourScope);
$scope.tour = null;
}
}
counter++;
});
}
}
};
return directiveDefinitionObject;
@ -131,15 +200,15 @@ angular.module("angular-tour", [])
// Signal: When the page location matches the given path.
signals.matchesLocation = function(locationPath) {
return function() {
return $location.path() == locationPath;
return function(tourScope) {
return $location.path() == tourScope._replaceData(locationPath);
};
};
// Signal: When an element is found in the page's DOM.
signals.elementAvaliable = function(elementPath) {
return function() {
return $(elementPath).length > 0;
return function(tourScope) {
return $(tourScope._replaceData(elementPath)).length > 0;
};
};