Move signin to use AJAX. Render all flask templates with the common header. Move the header to a partial. Add account recovery.
This commit is contained in:
parent
e182163d34
commit
4c15072c5a
17 changed files with 653 additions and 617 deletions
|
@ -136,6 +136,7 @@ quayApp = angular.module('quay', ['restangular', 'angularMoment', 'angulartics',
|
|||
when('/user/', {title: 'User Admin', templateUrl: '/static/partials/user-admin.html', controller: UserAdminCtrl}).
|
||||
when('/guide/', {title: 'Getting Started Guide', templateUrl: '/static/partials/guide.html', controller: GuideCtrl}).
|
||||
when('/plans/', {title: 'Plans and Pricing', templateUrl: '/static/partials/plans.html', controller: PlansCtrl}).
|
||||
when('/signin/', {title: 'Signin', templateUrl: '/static/partials/signin.html', controller: SigninCtrl}).
|
||||
when('/', {title: 'Hosted Private Docker Registry', templateUrl: '/static/partials/landing.html', controller: LandingCtrl}).
|
||||
otherwise({redirectTo: '/'});
|
||||
}]).
|
||||
|
|
|
@ -35,48 +35,101 @@ function getMarkedDown(string) {
|
|||
return Markdown.getSanitizingConverter().makeHtml(string || '');
|
||||
}
|
||||
|
||||
function HeaderCtrl($scope, UserService) {
|
||||
function HeaderCtrl($scope, $location, UserService, Restangular) {
|
||||
$scope.$watch( function () { return UserService.currentUser(); }, function (currentUser) {
|
||||
$scope.user = currentUser;
|
||||
}, true);
|
||||
|
||||
$('#repoSearch').typeahead({
|
||||
name: 'repositories',
|
||||
remote: {
|
||||
url: '/api/find/repository?query=%QUERY',
|
||||
filter: function(data) {
|
||||
var datums = [];
|
||||
for (var i = 0; i < data.repositories.length; ++i) {
|
||||
var repo = data.repositories[i];
|
||||
datums.push({
|
||||
'value': repo.name,
|
||||
'tokens': [repo.name, repo.namespace],
|
||||
'repo': repo
|
||||
});
|
||||
$scope.signout = function() {
|
||||
var signoutPost = Restangular.one('signout');
|
||||
signoutPost.customPOST().then(function() {
|
||||
UserService.load();
|
||||
$location.path('/');
|
||||
});
|
||||
}
|
||||
|
||||
$scope.$on('$includeContentLoaded', function() {
|
||||
// THIS IS BAD, MOVE THIS TO A DIRECTIVE
|
||||
$('#repoSearch').typeahead({
|
||||
name: 'repositories',
|
||||
remote: {
|
||||
url: '/api/find/repository?query=%QUERY',
|
||||
filter: function(data) {
|
||||
var datums = [];
|
||||
for (var i = 0; i < data.repositories.length; ++i) {
|
||||
var repo = data.repositories[i];
|
||||
datums.push({
|
||||
'value': repo.name,
|
||||
'tokens': [repo.name, repo.namespace],
|
||||
'repo': repo
|
||||
});
|
||||
}
|
||||
return datums;
|
||||
}
|
||||
},
|
||||
template: function (datum) {
|
||||
template = '<div class="repo-mini-listing">';
|
||||
template += '<i class="icon-hdd icon-large"></i>'
|
||||
template += '<span class="name">' + datum.repo.namespace +'/' + datum.repo.name + '</span>'
|
||||
if (datum.repo.description) {
|
||||
template += '<span class="description">' + getFirstTextLine(datum.repo.description) + '</span>'
|
||||
}
|
||||
return datums;
|
||||
}
|
||||
},
|
||||
template: function (datum) {
|
||||
template = '<div class="repo-mini-listing">';
|
||||
template += '<i class="icon-hdd icon-large"></i>'
|
||||
template += '<span class="name">' + datum.repo.namespace +'/' + datum.repo.name + '</span>'
|
||||
if (datum.repo.description) {
|
||||
template += '<span class="description">' + getFirstTextLine(datum.repo.description) + '</span>'
|
||||
}
|
||||
|
||||
template += '</div>'
|
||||
return template;
|
||||
},
|
||||
template += '</div>'
|
||||
return template;
|
||||
},
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
$('#repoSearch').on('typeahead:selected', function (e, datum) {
|
||||
$('#repoSearch').typeahead('setQuery', '');
|
||||
document.location = '/repository/' + datum.repo.namespace + '/' + datum.repo.name
|
||||
$('#repoSearch').on('typeahead:selected', function (e, datum) {
|
||||
$('#repoSearch').typeahead('setQuery', '');
|
||||
document.location = '/repository/' + datum.repo.namespace + '/' + datum.repo.name
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function SigninCtrl($scope, $location, $timeout, Restangular, KeyService, UserService) {
|
||||
$scope.githubClientId = KeyService.githubClientId;
|
||||
|
||||
var appendMixpanelId = function() {
|
||||
if (mixpanel.get_distinct_id !== undefined) {
|
||||
$scope.mixpanelDistinctIdClause = "&state=" + mixpanel.get_distinct_id();
|
||||
} else {
|
||||
// Mixpanel not yet loaded, try again later
|
||||
$timeout(appendMixpanelId, 200);
|
||||
}
|
||||
};
|
||||
|
||||
appendMixpanelId();
|
||||
|
||||
$scope.signin = function() {
|
||||
var signinPost = Restangular.one('signin');
|
||||
signinPost.customPOST($scope.user).then(function() {
|
||||
$scope.needsEmailVerification = false;
|
||||
$scope.invalidCredentials = false;
|
||||
|
||||
// Redirect to the landing page
|
||||
UserService.load();
|
||||
$location.path('/');
|
||||
}, function(result) {
|
||||
$scope.needsEmailVerification = result.data.needsEmailVerification;
|
||||
$scope.invalidCredentials = result.data.invalidCredentials;
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
$scope.sendRecovery = function() {
|
||||
var signinPost = Restangular.one('recovery');
|
||||
signinPost.customPOST($scope.recovery).then(function() {
|
||||
$scope.invalidEmail = false;
|
||||
$scope.sent = true;
|
||||
}, function(result) {
|
||||
$scope.invalidEmail = true;
|
||||
$scope.sent = false;
|
||||
});
|
||||
};
|
||||
};
|
||||
|
||||
function PlansCtrl($scope, UserService, PlanService) {
|
||||
$scope.plans = PlanService.planList();
|
||||
|
||||
|
@ -328,35 +381,38 @@ function RepoAdminCtrl($scope, Restangular, $routeParams, $rootScope) {
|
|||
var namespace = $routeParams.namespace;
|
||||
var name = $routeParams.name;
|
||||
|
||||
$('#userSearch').typeahead({
|
||||
name: 'users',
|
||||
remote: {
|
||||
url: '/api/users/%QUERY',
|
||||
filter: function(data) {
|
||||
var datums = [];
|
||||
for (var i = 0; i < data.users.length; ++i) {
|
||||
var user = data.users[i];
|
||||
datums.push({
|
||||
'value': user,
|
||||
'tokens': [user],
|
||||
'username': user
|
||||
});
|
||||
$scope.$on('$viewContentLoaded', function() {
|
||||
// THIS IS BAD, MOVE THIS TO A DIRECTIVE
|
||||
$('#userSearch').typeahead({
|
||||
name: 'users',
|
||||
remote: {
|
||||
url: '/api/users/%QUERY',
|
||||
filter: function(data) {
|
||||
var datums = [];
|
||||
for (var i = 0; i < data.users.length; ++i) {
|
||||
var user = data.users[i];
|
||||
datums.push({
|
||||
'value': user,
|
||||
'tokens': [user],
|
||||
'username': user
|
||||
});
|
||||
}
|
||||
return datums;
|
||||
}
|
||||
return datums;
|
||||
}
|
||||
},
|
||||
template: function (datum) {
|
||||
template = '<div class="user-mini-listing">';
|
||||
template += '<i class="icon-user icon-large"></i>'
|
||||
template += '<span class="name">' + datum.username + '</span>'
|
||||
template += '</div>'
|
||||
return template;
|
||||
},
|
||||
});
|
||||
},
|
||||
template: function (datum) {
|
||||
template = '<div class="user-mini-listing">';
|
||||
template += '<i class="icon-user icon-large"></i>'
|
||||
template += '<span class="name">' + datum.username + '</span>'
|
||||
template += '</div>'
|
||||
return template;
|
||||
},
|
||||
});
|
||||
|
||||
$('#userSearch').on('typeahead:selected', function(e, datum) {
|
||||
$('#userSearch').typeahead('setQuery', '');
|
||||
$scope.addNewPermission(datum.username);
|
||||
$('#userSearch').on('typeahead:selected', function(e, datum) {
|
||||
$('#userSearch').typeahead('setQuery', '');
|
||||
$scope.addNewPermission(datum.username);
|
||||
});
|
||||
});
|
||||
|
||||
$scope.addNewPermission = function(username) {
|
||||
|
|
Reference in a new issue