Merge pull request #1096 from simonoff/0.4-database-assets-refactoring

Assets refactoring
This commit is contained in:
Brad Rydzewski 2015-07-14 14:12:35 -04:00
commit 8b54d51e04
35 changed files with 2396 additions and 2379 deletions

BIN
cmd/drone-server/drone-server Executable file

Binary file not shown.

View file

@ -1,45 +1,46 @@
<!DOCTYPE html> <!DOCTYPE html>
<html ng-app="drone" lang="en"> <html ng-app="drone" lang="en">
<head> <head>
<meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1">
<base href="/"/> <base href="/"/>
<link href='//fonts.googleapis.com/css?family=Source+Sans+Pro:200,300,400,600,700' rel='stylesheet' type='text/css'> <link href='//fonts.googleapis.com/css?family=Source+Sans+Pro:200,300,400,600,700' rel='stylesheet' type='text/css'>
<link href='//fonts.googleapis.com/css?family=Open+Sans:400,600,300' rel='stylesheet' type='text/css'> <link href='//fonts.googleapis.com/css?family=Open+Sans:400,600,300' rel='stylesheet' type='text/css'>
<link href='//fonts.googleapis.com/css?family=Montserrat:400,700' rel='stylesheet' type='text/css'> <link href='//fonts.googleapis.com/css?family=Montserrat:400,700' rel='stylesheet' type='text/css'>
<link href='//cdn.rawgit.com/zavoloklom/material-design-iconic-font/master/css/material-design-iconic-font.min.css' rel='stylesheet' type='text/css'> <link href='//fonts.googleapis.com/icon?family=Material+Icons' rel='stylesheet' type='text/css'>
<link href='//cdnjs.cloudflare.com/ajax/libs/octicons/2.1.2/octicons.min.css' rel='stylesheet' type='text/css'> <link href='//cdnjs.cloudflare.com/ajax/libs/octicons/2.1.2/octicons.min.css' rel='stylesheet' type='text/css'>
<link rel="stylesheet" href="//fonts.googleapis.com/css?family=Droid+Sans+Mono" /> <link rel="stylesheet" href="//fonts.googleapis.com/css?family=Droid+Sans+Mono"/>
<link href='/static/styles/drone.css' rel='stylesheet' type='text/css'> <link href='/static/styles/drone.css' rel='stylesheet' type='text/css'>
<link rel="icon" href="/static/favicon.png"> <link rel="icon" href="/static/favicon.png">
</head> </head>
<body> <body>
<div role="main" ng-view ng-cloak></div> <div ui-view="layout"></div>
<script src="//cdnjs.cloudflare.com/ajax/libs/angular.js/1.3.15/angular.js"></script> <script src="//cdnjs.cloudflare.com/ajax/libs/angular.js/1.3.15/angular.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/angular.js/1.3.15/angular-route.js"></script> <script src="//cdnjs.cloudflare.com/ajax/libs/angular.js/1.3.15/angular-route.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/angular.js/1.3.15/angular-resource.js"></script> <script src="//cdnjs.cloudflare.com/ajax/libs/angular.js/1.3.15/angular-resource.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/angular-ui/0.4.0/angular-ui.js"></script> <script src="//cdnjs.cloudflare.com/ajax/libs/angular-ui/0.4.0/angular-ui.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/moment.js/2.6.0/moment.min.js"></script> <script src="//cdnjs.cloudflare.com/ajax/libs/angular-ui-router/0.2.15/angular-ui-router.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/moment.js/2.6.0/moment.min.js"></script>
<!-- main javascript application --> <!-- main javascript application -->
<script src="/static/scripts/term.js"></script> <script src="/static/scripts/term.js"></script>
<script src="/static/scripts/drone.js"></script> <script src="/static/scripts/drone.js"></script>
<script src="/static/scripts/controllers/repos.js"></script> <script src="/static/scripts/controllers/repos.js"></script>
<script src="/static/scripts/controllers/builds.js"></script> <script src="/static/scripts/controllers/builds.js"></script>
<script src="/static/scripts/controllers/users.js"></script> <script src="/static/scripts/controllers/users.js"></script>
<script src="/static/scripts/services/repos.js"></script> <script src="/static/scripts/services/repos.js"></script>
<script src="/static/scripts/services/builds.js"></script> <script src="/static/scripts/services/builds.js"></script>
<script src="/static/scripts/services/users.js"></script> <script src="/static/scripts/services/users.js"></script>
<script src="/static/scripts/services/logs.js"></script> <script src="/static/scripts/services/logs.js"></script>
<script src="/static/scripts/services/tokens.js"></script> <script src="/static/scripts/services/tokens.js"></script>
<script src="/static/scripts/services/feed.js"></script> <script src="/static/scripts/services/feed.js"></script>
<script src="/static/scripts/filters/filter.js"></script> <script src="/static/scripts/filters/filter.js"></script>
<script src="/static/scripts/filters/gravatar.js"></script> <script src="/static/scripts/filters/gravatar.js"></script>
<script src="/static/scripts/filters/time.js"></script> <script src="/static/scripts/filters/time.js"></script>
</body> </body>
</html> </html>

View file

@ -1,222 +1,240 @@
(function () { (function () {
/** /**
* BuildsCtrl responsible for rendering the repo's * BuildsCtrl responsible for rendering the repo's
* recent build history. * recent build history.
*/ */
function BuildsCtrl($scope, $routeParams, builds, repos, users, logs) { function BuildsCtrl($scope, $stateParams, builds, repos, users, logs) {
var owner = $stateParams.owner;
var name = $stateParams.name;
var fullName = owner + '/' + name;
var owner = $routeParams.owner; // Gets the currently authenticated user
var name = $routeParams.name; users.getCached().then(function (payload) {
var fullName = owner+'/'+name; $scope.user = payload.data;
});
// Gets the currently authenticated user // Gets a repository
users.getCached().then(function(payload){ repos.get(fullName).then(function (payload) {
$scope.user = payload.data; $scope.repo = payload.data;
}); }).catch(function (err) {
$scope.error = err;
});
// Gets a repository // Gets a list of builds
repos.get(fullName).then(function(payload){ builds.list(fullName).then(function (payload) {
$scope.repo = payload.data; $scope.builds = angular.isArray(payload.data) ? payload.data : [];
}).catch(function(err){ }).catch(function (err) {
$scope.error = err; $scope.error = err;
}); });
// Gets a list of builds $scope.watch = function (repo) {
builds.list(fullName).then(function(payload){ repos.watch(repo.full_name).then(function (payload) {
$scope.builds = angular.isArray(payload.data) ? payload.data : []; $scope.repo.starred = true;
}).catch(function(err){ });
$scope.error = err; };
});
$scope.watch = function(repo) { $scope.unwatch = function (repo) {
repos.watch(repo.full_name).then(function(payload) { repos.unwatch(repo.full_name).then(function () {
$scope.repo.starred = true; $scope.repo.starred = false;
}); });
} };
$scope.unwatch = function(repo) { repos.subscribe(fullName, function (event) {
repos.unwatch(repo.full_name).then(function() { var added = false;
$scope.repo.starred = false; for (var i = 0; i < $scope.builds.length; i++) {
}); var build = $scope.builds[i];
} if (event.number !== build.number) {
continue; // ignore
}
// update the build status
$scope.builds[i] = event;
$scope.$apply();
added = true;
}
repos.subscribe(fullName, function(event) { if (!added) {
var added = false; $scope.builds.push(event);
for (var i=0;i<$scope.builds.length;i++) { $scope.$apply();
var build = $scope.builds[i]; }
if (event.number !== build.number) { });
continue; // ignore }
}
// update the build status
$scope.builds[i] = event;
$scope.$apply();
added = true;
}
if (!added) { /**
$scope.builds.push(event); * BuildCtrl responsible for rendering a build.
$scope.$apply(); */
} function BuildCtrl($scope, $stateParams, $window, logs, builds, repos, users) {
}); var number = $stateParams.number;
} var owner = $stateParams.owner;
var name = $stateParams.name;
var fullName = owner + '/' + name;
/** // Gets the currently authenticated user
* BuildCtrl responsible for rendering a build. users.getCached().then(function (payload) {
*/ $scope.user = payload.data;
function BuildCtrl($scope, $routeParams, $window, logs, builds, repos, users) { });
var number = $routeParams.number; // Gets a repository
var owner = $routeParams.owner; repos.get(fullName).then(function (payload) {
var name = $routeParams.name; $scope.repo = payload.data;
var fullName = owner+'/'+name; }).catch(function (err) {
$scope.error = err;
});
// Gets the currently authenticated user // Gets the build
users.getCached().then(function(payload){ builds.get(fullName, number).then(function (payload) {
$scope.user = payload.data; $scope.build = payload.data;
}); }).catch(function (err) {
$scope.error = err;
});
// Gets a repository repos.subscribe(fullName, function (event) {
repos.get(fullName).then(function(payload){ if (event.number !== parseInt(number)) {
$scope.repo = payload.data; return; // ignore
}).catch(function(err){ }
$scope.error = err; // update the build
}); $scope.build = event;
$scope.$apply();
});
// Gets the build $scope.restart = function () {
builds.get(fullName, number).then(function(payload){ builds.restart(fullName, number).then(function (payload) {
$scope.build = payload.data; $scope.build = payload.data;
}).catch(function(err){ }).catch(function (err) {
$scope.error = err; $scope.error = err;
}); });
};
repos.subscribe(fullName, function(event) { $scope.cancel = function () {
if (event.number !== parseInt(number)) { builds.cancel(fullName, number).then(function (payload) {
return; // ignore $scope.build = payload.data;
} }).catch(function (err) {
// update the build $scope.error = err;
$scope.build = event; });
$scope.$apply(); };
});
} $scope.tail = function () {
tail = !tail;
};
}
/** /**
* BuildOutCtrl responsible for rendering a build output. * BuildOutCtrl responsible for rendering a build output.
*/ */
function BuildOutCtrl($scope, $routeParams, $window, logs, builds, repos, users) { function BuildOutCtrl($scope, $stateParams, $window, logs, builds, repos, users) {
var step = parseInt($routeParams.step) || 1; var step = parseInt($stateParams.step) || 1;
var number = $routeParams.number; var number = $stateParams.number;
var owner = $routeParams.owner; var owner = $stateParams.owner;
var name = $routeParams.name; var name = $stateParams.name;
var fullName = owner+'/'+name; var fullName = owner + '/' + name;
var streaming = false; var streaming = false;
var tail = false; var tail = false;
// Initiates streaming a build. // Initiates streaming a build.
var stream = function() { var stream = function () {
if (streaming) { if (streaming) {
return; return;
} }
streaming = true; streaming = true;
var convert = new Filter({stream:true,newline:false}); var convert = new Filter({stream: true, newline: false});
var term = document.getElementById("term"); var term = document.getElementById("term");
term.innerHTML = ""; term.innerHTML = "";
// subscribes to the build otuput. // subscribes to the build otuput.
logs.subscribe(fullName, number, step, function(data){ logs.subscribe(fullName, number, step, function (data) {
term.innerHTML += convert.toHtml(data.replace("\\n","\n")); term.innerHTML += convert.toHtml(data.replace("\\n", "\n"));
if (tail) { if (tail) {
// scrolls to the bottom of the page if enabled // scrolls to the bottom of the page if enabled
$window.scrollTo(0, $window.document.body.scrollHeight); $window.scrollTo(0, $window.document.body.scrollHeight);
} }
}); });
} };
// Gets the currently authenticated user // Gets the currently authenticated user
users.getCached().then(function(payload){ users.getCached().then(function (payload) {
$scope.user = payload.data; $scope.user = payload.data;
}); });
// Gets a repository // Gets a repository
repos.get(fullName).then(function(payload){ repos.get(fullName).then(function (payload) {
$scope.repo = payload.data; $scope.repo = payload.data;
}).catch(function(err){ }).catch(function (err) {
$scope.error = err; $scope.error = err;
}); });
// Gets the build // Gets the build
builds.get(fullName, number).then(function(payload){ builds.get(fullName, number).then(function (payload) {
$scope.build = payload.data; $scope.build = payload.data;
$scope.task = payload.data.jobs[step-1]; $scope.task = payload.data.jobs[step - 1];
if (['pending', 'killed'].indexOf($scope.task.status) !== -1) { if (['pending', 'killed'].indexOf($scope.task.status) !== -1) {
// do nothing // do nothing
} else if ($scope.task.status === 'running') { } else if ($scope.task.status === 'running') {
// stream the build // stream the build
stream(); stream();
} else { } else {
// fetch the logs for the finished build. // fetch the logs for the finished build.
logs.get(fullName, number, step).then(function(payload){ logs.get(fullName, number, step).then(function (payload) {
var convert = new Filter({stream:false,newline:false}); var convert = new Filter({stream: false, newline: false});
var term = document.getElementById("term") var term = document.getElementById("term")
term.innerHTML = convert.toHtml(payload.data); term.innerHTML = convert.toHtml(payload.data);
}).catch(function(err){ }).catch(function (err) {
$scope.error = err; $scope.error = err;
}); });
} }
}).catch(function(err){ }).catch(function (err) {
$scope.error = err; $scope.error = err;
}); });
$scope.restart = function() { repos.subscribe(fullName, function (event) {
builds.restart(fullName, number).then(function(payload){ if (event.number !== parseInt(number)) {
$scope.build = payload.data; return; // ignore
$scope.task = payload.data.builds[step-1]; }
}).catch(function(err){ // update the build
$scope.error = err; $scope.build = event;
}); console.log(event.builds);
}; $scope.task = event.builds[step - 1];
$scope.$apply();
$scope.cancel = function() { // start streaming the current build
builds.cancel(fullName, number).then(function(payload){ if ($scope.task.status === 'running') {
$scope.build = payload.data; stream();
$scope.task = payload.data.builds[step-1]; } else {
}).catch(function(err) { // resets our streaming state
$scope.error = err; streaming = false;
}); }
}; });
$scope.tail = function() { $scope.restart = function () {
tail = !tail; builds.restart(fullName, number).then(function (payload) {
}; $scope.build = payload.data;
$scope.task = payload.data.builds[step - 1];
}).catch(function (err) {
$scope.error = err;
});
};
repos.subscribe(fullName, function(event) { $scope.cancel = function () {
if (event.number !== parseInt(number)) { builds.cancel(fullName, number).then(function (payload) {
return; // ignore $scope.build = payload.data;
} $scope.task = payload.data.builds[step - 1];
// update the build }).catch(function (err) {
$scope.build = event; $scope.error = err;
$scope.task = event.builds[step-1]; });
$scope.$apply(); };
// start streaming the current build $scope.tail = function () {
if ($scope.task.status === 'running') { tail = !tail;
stream(); };
} else { }
// resets our streaming state
streaming = false;
}
});
}
angular
angular .module('drone')
.module('drone') .controller('BuildOutCtrl', BuildOutCtrl)
.controller('BuildOutCtrl', BuildOutCtrl) .controller('BuildCtrl', BuildCtrl)
.controller('BuildCtrl', BuildCtrl) .controller('BuildsCtrl', BuildsCtrl);
.controller('BuildsCtrl', BuildsCtrl);
})(); })();

View file

@ -4,10 +4,10 @@
* CommitsCtrl responsible for rendering the repo's * CommitsCtrl responsible for rendering the repo's
* recent commit history. * recent commit history.
*/ */
function CommitsCtrl($scope, $routeParams, builds, repos, users, logs) { function CommitsCtrl($scope, $stateParams, builds, repos, users, logs) {
var owner = $routeParams.owner; var owner = $stateParams.owner;
var name = $routeParams.name; var name = $stateParams.name;
var fullName = owner+'/'+name; var fullName = owner+'/'+name;
// Gets the currently authenticated user // Gets the currently authenticated user

View file

@ -1,116 +1,115 @@
(function () { (function () {
/** /**
* ReposCtrl responsible for rendering the user's * ReposCtrl responsible for rendering the user's
* repository home screen. * repository home screen.
*/ */
function ReposCtrl($scope, $routeParams, repos, users) { function ReposCtrl($scope, $stateParams, repos, users) {
// Gets the currently authenticated user
users.getCached().then(function (payload) {
$scope.user = payload.data;
});
// Gets the currently authenticated user // Gets a list of repos to display in the
users.getCached().then(function(payload){ // dropdown.
$scope.user = payload.data; repos.list().then(function (payload) {
}); $scope.repos = angular.isArray(payload.data) ? payload.data : [];
}).catch(function (err) {
$scope.error = err;
});
}
// Gets a list of repos to display in the /**
// dropdown. * RepoAddCtrl responsible for activaing a new
repos.list().then(function(payload){ * repository.
$scope.repos = angular.isArray(payload.data) ? payload.data : []; */
}).catch(function(err){ function RepoAddCtrl($scope, $location, repos, users) {
$scope.error = err;
});
}
/** // Gets the currently authenticated user
* RepoAddCtrl responsible for activaing a new users.getCached().then(function (payload) {
* repository. $scope.user = payload.data;
*/ });
function RepoAddCtrl($scope, $location, repos, users) {
// Gets the currently authenticated user $scope.add = function (slug) {
users.getCached().then(function(payload){ repos.post(slug).then(function (payload) {
$scope.user = payload.data; $location.path('/' + slug);
}); }).catch(function (err) {
$scope.error = err;
});
}
}
$scope.add = function(slug) { /**
repos.post(slug).then(function(payload) { * RepoEditCtrl responsible for editing a repository.
$location.path('/'+slug); */
}).catch(function(err){ function RepoEditCtrl($scope, $window, $location, $stateParams, repos, users) {
$scope.error = err; var owner = $stateParams.owner;
}); var name = $stateParams.name;
} var fullName = owner + '/' + name;
}
/** // Inject window for composing url
* RepoEditCtrl responsible for editing a repository. $scope.window = $window;
*/
function RepoEditCtrl($scope, $window, $location, $routeParams, repos, users) {
var owner = $routeParams.owner;
var name = $routeParams.name;
var fullName = owner+'/'+name;
// Inject window for composing url // Gets the currently authenticated user
$scope.window = $window; users.getCached().then(function (payload) {
$scope.user = payload.data;
});
// Gets the currently authenticated user // Gets a repository
users.getCached().then(function(payload){ repos.get(fullName).then(function (payload) {
$scope.user = payload.data; $scope.repo = payload.data;
}); }).catch(function (err) {
$scope.error = err;
});
// Gets a repository $scope.save = function (repo) {
repos.get(fullName).then(function(payload){ repo.timeout = parseInt(repo.timeout);
$scope.repo = payload.data; repos.update(repo).then(function (payload) {
}).catch(function(err){ $scope.repo = payload.data;
$scope.error = err; }).catch(function (err) {
}); $scope.error = err;
});
};
$scope.save = function(repo) { $scope.delete = function (repo) {
repo.timeout = parseInt(repo.timeout); repos.delete(repo).then(function (payload) {
repos.update(repo).then(function(payload) { $location.path('/');
$scope.repo = payload.data; }).catch(function (err) {
}).catch(function(err){ $scope.error = err;
$scope.error = err; });
}); };
}
$scope.delete = function(repo) { $scope.param = {};
repos.delete(repo).then(function(payload) { $scope.addParam = function (param) {
$location.path('/'); if (!$scope.repo.params) {
}).catch(function(err){ $scope.repo.params = {}
$scope.error = err; }
}); $scope.repo.params[param.key] = param.value;
} $scope.param = {};
$scope.param={} // auto-update
$scope.addParam = function(param) { repos.update($scope.repo).then(function (payload) {
if (!$scope.repo.params) { $scope.repo = payload.data;
$scope.repo.params = {} }).catch(function (err) {
} $scope.error = err;
$scope.repo.params[param.key]=param.value; });
$scope.param={} };
// auto-update $scope.deleteParam = function (key) {
repos.update($scope.repo).then(function(payload) { delete $scope.repo.params[key];
$scope.repo = payload.data;
}).catch(function(err){
$scope.error = err;
});
}
$scope.deleteParam = function(key) { // auto-update
delete $scope.repo.params[key]; repos.update($scope.repo).then(function (payload) {
$scope.repo = payload.data;
}).catch(function (err) {
$scope.error = err;
});
}
}
// auto-update angular
repos.update($scope.repo).then(function(payload) { .module('drone')
$scope.repo = payload.data; .controller('ReposCtrl', ReposCtrl)
}).catch(function(err){ .controller('RepoAddCtrl', RepoAddCtrl)
$scope.error = err; .controller('RepoEditCtrl', RepoEditCtrl);
});
}
}
angular
.module('drone')
.controller('ReposCtrl', ReposCtrl)
.controller('RepoAddCtrl', RepoAddCtrl)
.controller('RepoEditCtrl', RepoEditCtrl);
})(); })();

View file

@ -2,150 +2,251 @@
(function () { (function () {
/** /**
* Creates the angular application. * Creates the angular application.
*/ */
angular.module('drone', [ angular.module('drone', [
'ngRoute', 'ngRoute',
'ui.filters' 'ui.filters',
]); 'ui.router'
]);
/** /**
* Bootstraps the application and retrieves the * Bootstraps the application and retrieves the
* token from the * token from the
*/ */
function Authorize() { function Authorize() {
// First, parse the query string // First, parse the query string
var params = {}, queryString = location.hash.substring(1), var params = {}, queryString = location.hash.substring(1),
regex = /([^&=]+)=([^&]*)/g, m; regex = /([^&=]+)=([^&]*)/g, m;
// Loop through and retrieve the token // Loop through and retrieve the token
while (m = regex.exec(queryString)) { while (m = regex.exec(queryString)) {
params[decodeURIComponent(m[1])] = decodeURIComponent(m[2]); params[decodeURIComponent(m[1])] = decodeURIComponent(m[2]);
} }
// if the user has just received an auth token we // if the user has just received an auth token we
// should extract from the URL, save to local storage // should extract from the URL, save to local storage
// and then remove from the URL for good measure. // and then remove from the URL for good measure.
if (params.access_token) { if (params.access_token) {
localStorage.setItem("access_token", params.access_token); localStorage.setItem("access_token", params.access_token);
history.replaceState({}, document.title, location.pathname); history.replaceState({}, document.title, location.pathname);
} }
} }
/** /**
* Defines the route configuration for the * Defines the route configuration for the
* main application. * main application.
*/ */
function Config ($routeProvider, $httpProvider, $locationProvider) { function Config($stateProvider, $httpProvider, $locationProvider) {
// Resolver that will attempt to load the currently // Resolver that will attempt to load the currently
// authenticated user prior to loading the page. // authenticated user prior to loading the page.
var resolveUser = { var resolveUser = {
user: function(users) { user: function (users) {
return users.getCached(); return users.getCached();
} }
} };
$routeProvider $stateProvider
.when('/', { .state('app', {
templateUrl: '/static/scripts/views/repos.html', abstract: true,
controller: 'ReposCtrl', views: {
resolve: resolveUser 'layout': {
}) templateUrl: '/static/scripts/views/layout.html',
.when('/login', { controller: function ($scope, $routeParams, repos, users) {
templateUrl: '/static/scripts/views/login.html', users.getCached().then(function (payload) {
controller: 'UserLoginCtrl' $scope.user = payload.data;
}) });
.when('/profile', { }
templateUrl: '/static/scripts/views/user.html', }
controller: 'UserCtrl', }
resolve: resolveUser })
}) .state('app.index', {
.when('/users', { url: '/',
templateUrl: '/static/scripts/views/users.html', views: {
controller: 'UsersCtrl', 'toolbar': {
resolve: resolveUser templateUrl: '/static/scripts/views/repos/index/toolbar.html'
}) },
.when('/new', { 'content': {
templateUrl: '/static/scripts/views/repos_add.html', templateUrl: '/static/scripts/views/repos/index/content.html',
controller: 'RepoAddCtrl', controller: 'ReposCtrl',
resolve: resolveUser resolve: resolveUser
}) }
.when('/:owner/:name', { },
templateUrl: '/static/scripts/views/builds.html', title: 'Dashboard'
controller: 'BuildsCtrl', })
resolve: resolveUser .state('login', {
}) url: '/login',
.when('/:owner/:name/edit', { views: {
templateUrl: '/static/scripts/views/repos_edit.html', 'layout': {
controller: 'RepoEditCtrl', templateUrl: '/static/scripts/views/login.html',
resolve: resolveUser controller: 'UserLoginCtrl',
}) resolve: resolveUser
.when('/:owner/:name/edit/env', { }
templateUrl: '/static/scripts/views/repos_env.html', },
controller: 'RepoEditCtrl', title: 'Login'
resolve: resolveUser })
}) .state('app.profile', {
.when('/:owner/:name/delete', { url: '/profile',
templateUrl: '/static/scripts/views/repos_del.html', views: {
controller: 'RepoEditCtrl', 'toolbar': {templateUrl: '/static/scripts/views/profile/toolbar.html'},
resolve: resolveUser 'content': {
}) templateUrl: '/static/scripts/views/profile/content.html',
.when('/:owner/:name/:number', { controller: 'UserCtrl',
templateUrl: '/static/scripts/views/build.html', resolve: resolveUser
controller: 'BuildCtrl', }
resolve: resolveUser },
}) title: 'Profile'
.when('/:owner/:name/:number/:step', { })
templateUrl: '/static/scripts/views/build_out.html', .state('app.users', {
controller: 'BuildOutCtrl', url: '/users',
resolve: resolveUser views: {
}); 'toolbar': {templateUrl: '/static/scripts/views/users/toolbar.html'},
'content': {
templateUrl: '/static/scripts/views/users/content.html',
controller: 'UsersCtrl',
resolve: resolveUser
}
},
title: 'Users'
})
.state('app.new_repo', {
url: '/new',
views: {
'toolbar': {templateUrl: '/static/scripts/views/repos/add/toolbar.html'},
'content': {
templateUrl: '/static/scripts/views/repos/add/content.html',
controller: 'RepoAddCtrl',
resolve: resolveUser
}
},
title: 'Add Repository'
})
.state('app.builds', {
url: '/:owner/:name',
views: {
'toolbar': {
templateUrl: '/static/scripts/views/builds/index/toolbar.html',
controller: 'RepoEditCtrl',
resolve: resolveUser
},
'content': {
templateUrl: '/static/scripts/views/builds/index/content.html',
controller: 'BuildsCtrl'
}
},
title: 'Builds'
})
.state('app.repo_edit', {
url: '/:owner/:name/edit',
views: {
'toolbar': {
templateUrl: '/static/scripts/views/repos/toolbar.html',
controller: 'RepoEditCtrl',
resolve: resolveUser
},
'content': {
templateUrl: '/static/scripts/views/repos/edit.html',
controller: 'RepoEditCtrl',
resolve: resolveUser
}
},
title: 'Edit Repository'
})
.state('app.repo.env', {
url: '/:owner/:name/edit/env',
views: {
'toolbar': {templateUrl: '/static/scripts/views/repos/toolbar.html'},
'content': {templateUrl: '/static/scripts/views/repos/env.html'}
},
controller: 'RepoEditCtrl',
resolve: resolveUser
})
.state('app.repo.del', {
url: '/:owner/:name/delete',
views: {
'toolbar': {templateUrl: '/static/scripts/views/repos/toolbar.html'},
'content': {templateUrl: '/static/scripts/views/repos/del.html'}
},
controller: 'RepoEditCtrl',
resolve: resolveUser
})
.state('app.build', {
url: '/:owner/:name/:number',
views: {
'toolbar': {
templateUrl: '/static/scripts/views/builds/show/toolbar.html',
controller: 'BuildCtrl',
resolve: resolveUser
},
'content': {
templateUrl: '/static/scripts/views/builds/show/content.html',
controller: 'BuildCtrl',
resolve: resolveUser
}
},
title: 'Build'
})
.state('app.job', {
url: '/:owner/:name/:number/:step',
views: {
'toolbar': {
templateUrl: '/static/scripts/views/builds/step/toolbar.html',
controller: 'BuildOutCtrl',
resolve: resolveUser
},
'content': {
templateUrl: '/static/scripts/views/builds/step/content.html',
controller: 'BuildOutCtrl',
resolve: resolveUser
},
title: 'Build Job'
}
});
// Enables html5 mode // Enables html5 mode
$locationProvider.html5Mode(true) $locationProvider.html5Mode(true);
// Appends the Bearer token to authorize every // Appends the Bearer token to authorize every
// outbound http request. // outbound http request.
$httpProvider.defaults.headers.common.Authorization = 'Bearer '+localStorage.getItem('access_token'); $httpProvider.defaults.headers.common.Authorization = 'Bearer ' + localStorage.getItem('access_token');
// Intercepts every oubput http response and redirects // Intercepts every oubput http response and redirects
// the user to the logic screen if the request was rejected. // the user to the logic screen if the request was rejected.
$httpProvider.interceptors.push(function($q, $location) { $httpProvider.interceptors.push(function ($q, $location) {
return { return {
'responseError': function(rejection) { 'responseError': function (rejection) {
if (rejection.status === 401 && rejection.config.url !== "/api/user") { if (rejection.status === 401 && rejection.config.url !== "/api/user") {
$location.path('/login'); $location.path('/login');
} }
if (rejection.status === 0) { if (rejection.status === 0) {
// this happens when the app is down or // this happens when the app is down or
// the browser loses internet connectivity. // the browser loses internet connectivity.
} }
return $q.reject(rejection); return $q.reject(rejection);
} }
}; };
}); });
} }
function RouteChange($rootScope, repos, logs) {
$rootScope.$on('$stateChangeStart', function () {
repos.unsubscribe();
logs.unsubscribe();
});
function RouteChange($rootScope, repos, logs) { $rootScope.$on('$stateChangeSuccess', function (event, current) {
$rootScope.$on('$routeChangeStart', function (event, next) { if (current.title) {
repos.unsubscribe(); document.title = current.title + ' · drone';
logs.unsubscribe(); }
}); });
}
$rootScope.$on('$routeChangeSuccess', function (event, current, previous) { angular
if (current.$$route.title) { .module('drone')
document.title = current.$$route.title + ' · drone'; .config(Authorize)
} .config(Config)
}); .run(RouteChange);
}
angular
.module('drone')
.config(Authorize)
.config(Config)
.run(RouteChange);
})(); })();

View file

@ -2,116 +2,116 @@
(function () { (function () {
/** /**
* The RepoService provides access to repository * The RepoService provides access to repository
* data using REST API calls. * data using REST API calls.
*/ */
function RepoService($http, $window) { function RepoService($http, $window) {
var callback, var callback,
websocket, websocket,
token = localStorage.getItem('access_token'); token = localStorage.getItem('access_token');
/** /**
* Gets a list of all repositories. * Gets a list of all repositories.
*/ */
this.list = function() { this.list = function () {
return $http.get('/api/user/repos'); return $http.get('/api/user/repos');
}; };
/** /**
* Gets a repository by name. * Gets a repository by name.
* *
* @param {string} Name of the repository. * @param {string} Name of the repository.
*/ */
this.get = function(repoName) { this.get = function (repoName) {
return $http.get('/api/repos/'+repoName); return $http.get('/api/repos/' + repoName);
}; };
/** /**
* Creates a new repository. * Creates a new repository.
* *
* @param {object} JSON representation of a repository. * @param {object} JSON representation of a repository.
*/ */
this.post = function(repoName) { this.post = function (repoName) {
return $http.post('/api/repos/' + repoName); return $http.post('/api/repos/' + repoName);
}; };
/** /**
* Updates an existing repository. * Updates an existing repository.
* *
* @param {object} JSON representation of a repository. * @param {object} JSON representation of a repository.
*/ */
this.update = function(repo) { this.update = function (repo) {
return $http.patch('/api/repos/'+repo.full_name, repo); return $http.patch('/api/repos/' + repo.full_name, repo);
}; };
/** /**
* Deletes a repository. * Deletes a repository.
* *
* @param {string} Name of the repository. * @param {string} Name of the repository.
*/ */
this.delete = function(repoName) { this.delete = function (repoName) {
return $http.delete('/api/repos/'+repoName); return $http.delete('/api/repos/' + repoName);
}; };
/** /**
* Watch a repository. * Watch a repository.
* *
* @param {string} Name of the repository. * @param {string} Name of the repository.
*/ */
this.watch = function(repoName) { this.watch = function (repoName) {
return $http.post('/api/repos/'+repoName+'/watch'); return $http.post('/api/repos/' + repoName + '/watch');
}; };
/** /**
* Unwatch a repository. * Unwatch a repository.
* *
* @param {string} Name of the repository. * @param {string} Name of the repository.
*/ */
this.unwatch = function(repoName) { this.unwatch = function (repoName) {
return $http.delete('/api/repos/'+repoName+'/unwatch'); return $http.delete('/api/repos/' + repoName + '/unwatch');
}; };
var callback, var callback,
events, events,
token = localStorage.getItem('access_token'); token = localStorage.getItem('access_token');
/** /**
* Subscribes to a live update feed for a repository * Subscribes to a live update feed for a repository
* *
* @param {string} Name of the repository. * @param {string} Name of the repository.
*/ */
this.subscribe = function(repo, _callback) { this.subscribe = function (repo, _callback) {
callback = _callback; callback = _callback;
events = new EventSource("/api/stream/" + repo + "?access_token=" + token, { withCredentials: true }); events = new EventSource("/api/stream/" + repo + "?access_token=" + token, {withCredentials: true});
events.onmessage = function (event) { events.onmessage = function (event) {
if (callback !== undefined) { if (callback !== undefined) {
callback(angular.fromJson(event.data)); callback(angular.fromJson(event.data));
} }
}; };
events.onerror = function (event) { events.onerror = function (event) {
callback = undefined; callback = undefined;
if (events !== undefined) { if (events !== undefined) {
events.close(); events.close();
events = undefined; events = undefined;
} }
console.log('user event stream closed due to error.', event); console.log('user event stream closed due to error.', event);
}; };
}; };
this.unsubscribe = function() { this.unsubscribe = function () {
callback = undefined; callback = undefined;
if (events !== undefined) { if (events !== undefined) {
events.close(); events.close();
events = undefined; events = undefined;
} }
}; };
} }
angular angular
.module('drone') .module('drone')
.service('repos', RepoService); .service('repos', RepoService);
})(); })();

View file

@ -1,64 +0,0 @@
<header>
<a class="logo float-left" href="/"></a>
<a class="menu-item settings float-right" href="/profile"></a>
<a class="menu-item users float-right" href="/users" ng-if="user.admin"></a>
<a class="menu-item help float-right" href="http://readme.drone.io" target="_blank"></a>
<a class="menu-item user-name float-right" href="/profile">{{ "+"+user.login }}</a>
</header>
<div class="toolbar">
<div class="breadcrumb" style="position:relative;top:0px;">
<a ng-href="/{{ repo.full_name }}" class="icon icon-home"></a>
<a ng-href="/{{ repo.full_name }}">{{ repo.owner }} / {{ repo.name }}</a>
<span class="spacer"></span>
<a ng-href="#">{{ build.number }}</a>
</div>
<div class="menu">
<a href="settings.html" class="icon icon-settings"></a>
<a ng-href="/{{ repo.full_name }}/edit" class="nav-item settings float-right"></a>
<button ng-click="watch(repo)" ng-if="!repo.starred" class="nav-item star float-right"></button>
<button ng-click="unwatch(repo)" ng-if="repo.starred" class="nav-item unstar float-right"></button>
</div>
</div>
<article>
<section class="commit-section">
<div class="row build-row">
<div>
<div ng-class="[ 'build-num', build.status ]"></div>
</div>
<div>
<h3>{{ build.head_commit.message }}</h3>
<p><strong>{{ build.head_commit.author.login }}</strong> pushed to <strong>{{ build.head_commit.branch }}</strong> {{ build.started_at | fromNow }}</p>
<div style="position:absolute;top:30px;right:30px;color:#CCC;"># {{build.number}}</div>
</div>
</div>
</section>
<section>
<a class="row build-row sub-build-row" ng-repeat="job in build.jobs" ng-href="{{ repo.full_name }}/{{ build.number }}/{{ job.number }}">
<div>
<div ng-class="[ 'build-num', build.status ]"></div>
</div>
<div>
<h3>
<div ng-repeat="(key, value) in job.environment">
{{ key.toUpperCase() }}={{ value }}
</div>
</h3>
<div style="position:absolute;top:30px;right:30px;color:#CCC;"># {{job.number}}</div>
</div>
</a>
</section>
</article>
<button ng-if="build.status !== 'pending' && build.status !== 'running'" ng-click="restart()">Restart</button>
<button ng-if="build.status === 'pending' || build.status === 'running'" ng-click="cancel()">Cancel</button>

View file

@ -1,68 +0,0 @@
<header>
<a class="logo float-left" href="/"></a>
<a class="menu-item settings float-right" href="/profile"></a>
<a class="menu-item users float-right" href="/users" ng-if="user.admin"></a>
<a class="menu-item help float-right" href="http://readme.drone.io" target="_blank"></a>
<a class="menu-item user-name float-right" href="/profile">{{ "+"+user.login }}</a>
</header>
<div class="toolbar">
<div class="breadcrumb" style="position:relative;top:0px;">
<a ng-href="/{{ repo.full_name }}/{{ build.sequence }}" class="icon icon-home"></a>
<a ng-href="/{{ repo.full_name }}">{{ repo.owner }} / {{ repo.name }}</a>
<span class="spacer"></span>
<a ng-href="/{{ repo.full_name }}/{{ build.sequence }}">{{ build.sequence }}</a>
<span class="spacer"></span>
<a href="#">{{ task.sequence }}</a>
</div>
<div class="menu">
<a ng-href="/{{ repo.full_name }}/edit" class="nav-item settings float-right"></a>
<button ng-click="watch(repo)" ng-if="!repo.starred" class="nav-item star float-right"></button>
<button ng-click="unwatch(repo)" ng-if="repo.starred" class="nav-item unstar float-right"></button>
</div>
</div>
<article>
<section class="commit-section">
<div class="row build-row">
<div>
<div ng-class="[ 'build-num', task.status ]" ng-if="task"></div>
<div ng-class="[ 'build-num', build.status ]" ng-if="!task"></div>
</div>
<div>
<h3>{{ build.head_commit.message }}</h3>
<p><strong>{{ build.head_commit.author.login }}</strong> pushed to <strong>{{ build.head_commit.branch }}</strong> {{ build.started_at | fromNow }}</p>
</div>
</div>
<div class="row build-row sub-build-row" ng-if="build.jobs.length > 1">
<div>
</div>
<div>
<h3 style="margin-top:0px">
<div ng-repeat="(key, value) in task.environment">
{{ key.toUpperCase() }}={{ value }}
</div>
</h3>
</div>
</div>
</section>
<pre id="term" ng-if="task && task.status !== 'pending'"></pre>
<button class="fab" ng-if="build.status === 'running'" ng-click="tail()"></button>
</article>
<button ng-if="build.status !== 'pending' && build.status !== 'running'" ng-click="restart()">Restart</button>
<button ng-if="build.status === 'pending' || build.status === 'running'" ng-click="cancel()">Cancel</button>

View file

@ -1,39 +0,0 @@
<header>
<a class="logo float-left" href="/"></a>
<a class="menu-item settings float-right" href="/profile"></a>
<a class="menu-item users float-right" href="/users" ng-if="user.admin"></a>
<a class="menu-item help float-right" href="http://readme.drone.io" target="_blank"></a>
<a class="menu-item user-name float-right" href="/profile">{{ "+"+user.login }}</a>
</header>
<div class="toolbar">
<div class="breadcrumb" style="position:relative;top:0px;">
<a href="/" class="icon icon-home"></a>
<a href="#">{{ repo.owner }} / {{ repo.name }}</a>
</div>
<div class="menu">
<a ng-href="/{{ repo.full_name }}/edit" class="nav-item settings float-right" ng-if="repo.permissions.pull"></a>
<button ng-click="watch(repo)" ng-if="!repo.starred && user" class="nav-item star float-right"></button>
<button ng-click="unwatch(repo)" ng-if="repo.starred && user" class="nav-item unstar float-right"></button>
</div>
</div>
<article>
<section>
<a class="row build-row" ng-repeat="build in builds | orderBy:'-number'" ng-href="/{{ repo.full_name }}/{{ build.number }}">
<div>
<div ng-class="[ 'build-num', build.status ]"></div>
</div>
<div>
<h3>{{ build.head_commit.message }}</h3>
<p><strong>{{ build.head_commit.author.login }}</strong> pushed to <strong>{{ build.head_commit.branch }}</strong> {{ build.started_at | fromNow }}</p>
<div style="position:absolute;top:30px;right:30px;color:#CCC;"># {{build.number}}</div>
</div>
</a>
</section>
</article>

View file

@ -0,0 +1,18 @@
<article>
<section>
<a class="row build-row" ng-repeat="build in builds | orderBy:'-number'" ng-href="/{{ repo.full_name }}/{{ build.number }}">
<div>
<div ng-class="[ 'build-num', build.status ]"></div>
</div>
<div>
<h3>{{ build.head_commit.message }}</h3>
<p>
<strong>{{ build.head_commit.author.login }}</strong> pushed to <strong>{{ build.head_commit.branch}}</strong> {{ build.started_at | fromNow }}
</p>
<div style="position:absolute;top:30px;right:30px;color:#CCC;"># {{build.number}}</div>
</div>
</a>
</section>
</article>

View file

@ -0,0 +1,18 @@
<div class="breadcrumb" style="position:relative;top:0px;">
<a href="/" class="icon icon-home">
<i class="material-icons md-18">home</i>
</a>
<a href="#">{{ repo.owner }} / {{ repo.name }}</a>
</div>
<div class="menu">
<a ng-href="/{{ repo.full_name }}/edit" class="nav-item settings float-right" ng-if="repo.permissions.pull">
<i class="material-icons md-18">edit</i>
</a>
<button ng-click="watch(repo)" ng-if="!repo.starred && user" class="nav-item star float-right">
<i class="material-icons md-18">star_border</i>
</button>
<button ng-click="unwatch(repo)" ng-if="repo.starred && user" class="nav-item unstar float-right">
<i class="material-icons md-18">star</i>
</button>
</div>

View file

@ -0,0 +1,40 @@
<article>
<section class="commit-section">
<div class="row build-row">
<div>
<div ng-class="[ 'build-num', build.status ]"></div>
</div>
<div>
<h3>{{ build.head_commit.message }}</h3>
<p><strong>{{ build.head_commit.author.login }}</strong> pushed to <strong>{{ build.head_commit.branch}}</strong> {{ build.started_at | fromNow }}</p>
<div style="position:absolute;top:30px;right:30px;color:#CCC;"># {{build.number}}</div>
</div>
</div>
</section>
<p style="padding-top: 20px;">
<h3><strong>Build jobs</strong></h3>
</p>
<section>
<a class="row build-row sub-build-row" ng-repeat="job in build.jobs" ng-href="{{ repo.full_name }}/{{ build.number }}/{{ job.number }}">
<div>
<div ng-class="[ 'build-num', build.status ]"></div>
</div>
<div>
<h3>
<div ng-repeat="(key, value) in job.environment">
{{ key.toUpperCase() }}={{ value }}
</div>
</h3>
<div style="position:absolute;top:30px;right:30px;color:#CCC;"># {{job.number}}</div>
</div>
</a>
</section>
</article>
<div style="padding-left: 20px;">
<button ng-if="build.status !== 'pending' && build.status !== 'running'" ng-click="restart()">Restart</button>
<button ng-if="build.status === 'pending' || build.status === 'running'" ng-click="cancel()">Cancel</button>
</div>

View file

@ -0,0 +1,20 @@
<div class="breadcrumb" style="position:relative;top:0px;">
<a ng-href="/{{ repo.full_name }}" class="icon icon-home">
<i class="material-icons md-18">home</i>
</a>
<a ng-href="/{{ repo.full_name }}">{{ repo.owner }} / {{ repo.name }}</a>
<span class="spacer"></span>
<a ng-href="#">#{{ build.number }}</a>
</div>
<div class="menu">
<a ng-href="/{{ repo.full_name }}/edit" class="nav-item settings float-right" ng-if="repo.permissions.pull">
<i class="material-icons md-18">edit</i>
</a>
<button ng-click="watch(repo)" ng-if="!repo.starred && user" class="nav-item star float-right">
<i class="material-icons md-18">star_border</i>
</button>
<button ng-click="unwatch(repo)" ng-if="repo.starred && user" class="nav-item unstar float-right">
<i class="material-icons md-18">star</i>
</button>
</div>

View file

@ -0,0 +1,37 @@
<article>
<section class="commit-section">
<div class="row build-row">
<div>
<div ng-class="[ 'build-num', task.status ]" ng-if="task"></div>
<div ng-class="[ 'build-num', build.status ]" ng-if="!task"></div>
</div>
<div>
<h3>{{ build.head_commit.message }}</h3>
<p><strong>{{ build.head_commit.author.login }}</strong> pushed to <strong>{{ build.head_commit.branch}}</strong> {{ build.started_at | fromNow }}</p>
</div>
</div>
<div class="row build-row sub-build-row" ng-if="build.jobs.length > 1">
<div>
</div>
<div>
<h3 style="margin-top:0px">
<div ng-repeat="(key, value) in task.environment">
{{ key.toUpperCase() }}={{ value }}
</div>
</h3>
</div>
</div>
</section>
<pre id="term" ng-if="task && task.status !== 'pending'"></pre>
<button class="fab" ng-if="build.status === 'running'" ng-click="tail()"></button>
</article>
<button ng-if="build.status !== 'pending' && build.status !== 'running'" ng-click="restart()">Restart</button>
<button ng-if="build.status === 'pending' || build.status === 'running'" ng-click="cancel()">Cancel</button>

View file

@ -0,0 +1,22 @@
<div class="breadcrumb" style="position:relative;top:0px;">
<a ng-href="/{{ repo.full_name }}/{{ build.sequence }}" class="icon icon-home">
<i class="material-icons md-18">home</i>
</a>
<a ng-href="/{{ repo.full_name }}">{{ repo.owner }} / {{ repo.name }}</a>
<span class="spacer">&nbsp;</span>
<a ng-href="/{{ repo.full_name }}/{{ build.number }}">Build # {{ build.number }}</a>
<span class="spacer"></span>
<a href="#">Job #{{ task.number }}</a>
</div>
<div class="menu">
<a ng-href="/{{ repo.full_name }}/edit" class="nav-item settings float-right" ng-if="repo.permissions.pull">
<i class="material-icons md-18">edit</i>
</a>
<button ng-click="watch(repo)" ng-if="!repo.starred && user" class="nav-item star float-right">
<i class="material-icons md-18">star_border</i>
</button>
<button ng-click="unwatch(repo)" ng-if="repo.starred && user" class="nav-item unstar float-right">
<i class="material-icons md-18">star</i>
</button>
</div>

View file

@ -0,0 +1,15 @@
<header>
<a class="logo float-left" href="/"></a>
<a class="menu-item help float-right" href="http://readme.drone.io" target="_blank">
<i class="material-icons md-18">help</i>
</a>
<a class="menu-item users float-right" href="/users" ng-if="user.admin">
<i class="material-icons md-18">supervisor_account</i>
</a>
<a class="menu-item settings float-right" href="/profile">
<i class="material-icons md-18">settings</i>
</a>
<a class="menu-item user-name float-right" href="/profile">{{ "+"+user.login }}</a>
</header>
<div class="toolbar" ui-view="toolbar"></div>
<div ui-view="content"></div>

View file

@ -1,67 +1,74 @@
<style> <style>
html, body { html, body {
background:#EEEEEE; background: #EEEEEE;
padding:0px; padding: 0px;
margin:0px; margin: 0px;
font-family:"Roboto"; font-family: "Roboto";
font-size:15px; font-size: 15px;
text-transform:uppercase; text-transform: uppercase;
width:100%; width: 100%;
height:100%; height: 100%;
} }
a.box {
background:#FFF; a.box {
width:250px; background: #FFF;
padding:20px; width: 250px;
box-shadow: 0px 0px 0 rgba(255,255,255,0.05); padding: 20px;
-webkit-transition: all .5s; box-shadow: 0px 0px 0 rgba(255, 255, 255, 0.05);
-webkit-box-flex: 0; -webkit-transition: all .5s;
display:block; -webkit-box-flex: 0;
text-decoration:none; display: block;
border-radius:3px; text-decoration: none;
} border-radius: 3px;
a.box:hover { }
box-shadow: 7px 7px 0 rgba(255,255,255,0.05);
} a.box:hover {
div.logo { box-shadow: 7px 7px 0 rgba(255, 255, 255, 0.05);
background: url(/static/images/logo.svg) no-repeat center center;; }
background-size:72px;
height:150px; div.logo {
-webkit-transition: all .5s; background: url(/static/images/logo.svg) no-repeat center center;
} background-size: 72px;
div.login { height: 150px;
text-align: center; -webkit-transition: all .5s;
padding: 15px; }
color: #424242;
font-size: 18px; div.login {
text-transform: uppercase; text-align: center;
border-radius: 3px; padding: 15px;
-webkit-transition: all .5s; color: #424242;
background: #424242; font-size: 18px;
color: rgba(255,255,255,0.7); text-transform: uppercase;
} border-radius: 3px;
body > div { -webkit-transition: all .5s;
width:100%; background: #424242;
height:100%; color: rgba(255, 255, 255, 0.7);
display: -webkit-box; }
display: -webkit-flex;
display: flex; body > div {
-webkit-box-align: center; width: 100%;
-webkit-align-items: center; height: 100%;
align-items: center; display: -webkit-box;
-webkit-box-pack: center; display: -webkit-flex;
-webkit-justify-content: center; display: flex;
justify-content: center; -webkit-box-align: center;
} -webkit-align-items: center;
</style> align-items: center;
-webkit-box-pack: center;
-webkit-justify-content: center;
justify-content: center;
}
</style>
<a href="/authorize" target="_self" class="box"> <a href="/authorize" target="_self" class="box">
<div class="logo"></div> <div class="logo"></div>
<div ng-switch="error" class="alert alert-error" ng-if="error"> <div ng-switch="error" class="alert alert-error" ng-if="error">
<div ng-switch-when="internal_error">Oops. There was an unexpected error. Please try again.</div> <div ng-switch-when="internal_error">Oops. There was an unexpected error. Please try again.</div>
<div ng-switch-when="user_not_found">There was an error authorizing your account.</div> <div ng-switch-when="user_not_found">There was an error authorizing your account.</div>
<div ng-switch-when="access_denied_org">Login is restricted to approved organization members only</div> <div ng-switch-when="access_denied_org">Login is restricted to approved organization members only</div>
<div ng-switch-when="access_denied">Self-registration is disabled. Please contact the system admin to grant access.</div> <div ng-switch-when="access_denied">Self-registration is disabled. Please contact the system admin to grant
</div> access.
<div class="login">Login</div> </div>
</div>
<div class="login">Login</div>
</a> </a>

View file

@ -1,19 +1,3 @@
<header>
<a class="logo float-left" href="/"></a>
<a class="menu-item settings float-right" href="/profile"></a>
<a class="menu-item users float-right" href="/users" ng-if="user.admin"></a>
<a class="menu-item help float-right" href="http://readme.drone.io" target="_blank"></a>
<a class="menu-item user-name float-right" href="/profile">{{ "+"+user.login }}</a>
</header>
<div class="toolbar">
<div class="breadcrumb" style="position:relative;top:0px;">
<a href="/" class="icon icon-home"></a>
<a href="#">Profile</a>
</div>
</div>
<article> <article>
<section> <section>
<h2>Login info</h2> <h2>Login info</h2>
@ -34,8 +18,12 @@
<section> <section>
<h2>Tokens</h2> <h2>Tokens</h2>
<form> <form>
<input type="label" ng-model="newToken.label" /> <div style="padding-left: 20px; float: left;">
<input type="label" ng-model="newToken.label" />
</div>
<div style="padding-top: 20px; padding-left: 20px; float: left;">
<button ng-click="createToken(newToken)">Create</button> <button ng-click="createToken(newToken)">Create</button>
</div>
</form> </form>
<div class="alert" ng-if="tokens && tokens.length === 0">No Personal Tokens Exist</div> <div class="alert" ng-if="tokens && tokens.length === 0">No Personal Tokens Exist</div>

View file

@ -0,0 +1,6 @@
<div class="breadcrumb" style="position:relative;top:0px;">
<a href="/" class="icon icon-home">
<i class="material-icons md-18">home</i>
</a>
<a href="#">Profile</a>
</div>

View file

@ -1,34 +0,0 @@
<header>
<a class="logo float-left" href="/"></a>
<a class="menu-item settings float-right" href="/profile"></a>
<a class="menu-item users float-right" href="/users" ng-if="user.admin"></a>
<a class="menu-item help float-right" href="http://readme.drone.io" target="_blank"></a>
<a class="menu-item user-name float-right" href="/profile">{{ "+"+user.login }}</a>
</header>
<div class="toolbar">
<div class="breadcrumb" style="position:relative;top:0px;">
<a href="#">Dashboard</a>
</div>
<div class="menu">
<a ng-href="/new" class="nav-item add float-right"></a>
</div>
</div>
<article>
<section>
<a class="row build-row" ng-repeat="repo in repos | orderBy:'full_name'" ng-href="/{{ repo.full_name }}">
<div>
<div class="icon icon-repo"></div>
</div>
<div>
<h3>{{ repo.owner }} / {{ repo.name }}</h3>
<p>{{ repo.clone_url }}</p>
</div>
</a>
</section>
</article>

View file

@ -1,18 +1,3 @@
<header>
<a class="logo float-left" href="/"></a>
<a class="menu-item settings float-right" href="/profile"></a>
<a class="menu-item users float-right" href="/users" ng-if="user.admin"></a>
<a class="menu-item help float-right" href="http://readme.drone.io" target="_blank"></a>
<a class="menu-item user-name float-right" href="/profile">{{ "+"+user.login }}</a>
</header>
<div class="toolbar">
<div class="breadcrumb" style="position:relative;top:0px;">
<a href="/" class="icon icon-home"></a>
<a href="#">Add Repository</a>
</div>
</div>
<article> <article>
<section style="background:transparent !important;"> <section style="background:transparent !important;">
<p style="color:#9E9E9E;font-size:15px;line-height:22px;">Register your repository with Drone to enable automated testing. Note that Drone <p style="color:#9E9E9E;font-size:15px;line-height:22px;">Register your repository with Drone to enable automated testing. Note that Drone

View file

@ -0,0 +1,6 @@
<div class="breadcrumb" style="position:relative;top:0px;">
<a href="/" class="icon icon-home">
<i class="material-icons md-18">home</i>
</a>
<a href="#">Add Repository</a>
</div>

View file

@ -0,0 +1,17 @@
<article>
<section style="padding:30px; background-color:#EF5350;">
<button ng-click="delete(repo.full_name)" style="color:rgba(255,255,255,0.9);
text-transform: uppercase;
text-decoration: none;
border: 1px solid rgba(255,255,255,0.9);
padding: 10px;
background:transparent;
display:inline-block;
cursor:pointer;
margin-right: 10px;">Delete</button>
<span style="color:rgba(255,255,255,0.9);font-size:16px;">Warning: this action cannot be undone.</span>
</section>
</article>

View file

@ -0,0 +1,75 @@
<article>
<section>
<h2>Settings</h2>
<div class="row">
<div>Post Commit Hooks</div>
<div>
<input id="post_commits" type="checkbox" hidden="hidden" ng-model="repo.hooks.push" ng-change="save(repo)"/>
<label for="post_commits" class="switch"></label>
</div>
</div>
<div class="row">
<div>Pull Request Hooks</div>
<div>
<input id="pull_requests" type="checkbox" hidden="hidden" ng-model="repo.hooks.pull_request"
ng-change="save(repo)"/>
<label for="pull_requests" class="switch"></label>
</div>
</div>
<a class="row" ng-href="{{ repo.full_name }}/edit/env">
<div>Private Variables</div>
<div>
Inject private variables into your build environment
</div>
</a>
<a class="row" ng-href="{{ repo.full_name }}/delete">
<div>Delete</div>
<div>Delete this repository and its build history</div>
</a>
</section>
<section ng-if="user.admin">
<h2>Admin settings</h2>
<div class="row">
<div>Trusted (Evelvate Privilege)</div>
<div>
<input id="trusted" type="checkbox" hidden="hidden" ng-model="repo.trusted" ng-change="save(repo)"/>
<label for="trusted" class="switch"></label>
</div>
</div>
<div class="row">
<div>Timeout in minutes</div>
<div>
<input type="range" ng-model="repo.timeout" min="0" max="900" ng-blur="save(repo)"/>
<span class="slider-label">{{ repo.timeout }} minutes</span>
</div>
</div>
</section>
<section>
<h2>Badges</h2>
<div class="row">
<div>Markdown</div>
<div>
<pre class="snippet">[![Build Status]({{ window.location.origin }}/api/badges/{{ repo.full_name }}/status.svg)]({{ window.location.origin }}/{{ repo.full_name }})</pre>
</div>
</div>
<div class="row">
<div>CCMenu</div>
<div>
<pre class="snippet">{{ window.location.origin }}/api/badges/{{ repo.full_name }}/cc.xml</pre>
</div>
</div>
</section>
<section>
<h2>Public Key</h2>
<div>
<pre class="snippet snippet-padding">{{ repo.keypair.public }}</pre>
</div>
</section>
</article>

View file

@ -1,25 +1,3 @@
<header>
<a class="logo float-left" href="/"></a>
<a class="menu-item settings float-right" href="/profile"></a>
<a class="menu-item users float-right" href="/users" ng-if="user.admin"></a>
<a class="menu-item help float-right" href="http://readme.drone.io" target="_blank"></a>
<a class="menu-item user-name float-right" href="/profile">{{ "+"+user.login }}</a>
</header>
<div class="toolbar">
<div class="breadcrumb" style="position:relative;top:0px;">
<a href="/{{ repo.full_name }}/edit" class="icon icon-home"></a>
<a ng-href="/{{ repo.full_name }}">{{ repo.owner }} / {{ repo.name }}</a>
</div>
<div class="menu">
<a ng-href="/{{ repo.full_name }}/edit" class="nav-item settings float-right"></a>
<button ng-click="watch(repo)" ng-if="!repo.starred" class="nav-item star float-right"></button>
<button ng-click="unwatch(repo)" ng-if="repo.starred" class="nav-item unstar float-right"></button>
</div>
</div>
<article> <article>
<section style="padding:30px;"> <section style="padding:30px;">
<h2 style=" padding-left: 0px; <h2 style=" padding-left: 0px;
@ -42,4 +20,4 @@ font-family: Roboto;
text-transform: uppercase;">add</button> text-transform: uppercase;">add</button>
</form> </form>
</section> </section>
</article> </article>

View file

@ -0,0 +1,14 @@
<article>
<section>
<a class="row build-row" ng-repeat="repo in repos | orderBy:'full_name'" ng-href="/{{ repo.full_name }}">
<div>
<div class="icon icon-repo"></div>
</div>
<div>
<h3>{{ repo.owner }} / {{ repo.name }}</h3>
<p>{{ repo.clone_url }}</p>
</div>
</a>
</section>
</article>

View file

@ -0,0 +1,9 @@
<div class="breadcrumb" style="position:relative;top:0px;">
<a href="#">Dashboard</a>
</div>
<div class="menu">
<a ng-href="/new" class="nav-item add float-right">
<i class="material-icons">add</i>
</a>
</div>

View file

@ -0,0 +1,18 @@
<div class="breadcrumb">
<a href="/{{ repo.full_name }}/edit" class="icon icon-home">
<i class="material-icons md-18">home</i>
</a>
<a ng-href="/{{ repo.full_name }}">{{ repo.owner }} / {{ repo.name }}</a>
</div>
<div class="menu">
<a ng-href="/{{ repo.full_name }}/edit" class="nav-item settings float-right" ng-if="repo.permissions.pull">
<i class="material-icons md-18">edit</i>
</a>
<button ng-click="watch(repo)" ng-if="!repo.starred && user" class="nav-item star float-right">
<i class="material-icons md-18">star_border</i>
</button>
<button ng-click="unwatch(repo)" ng-if="repo.starred && user" class="nav-item unstar float-right">
<i class="material-icons md-18">star</i>
</button>
</div>

View file

@ -1,42 +0,0 @@
<header>
<a class="logo float-left" href="/"></a>
<a class="menu-item settings float-right" href="/profile"></a>
<a class="menu-item users float-right" href="/users" ng-if="user.admin"></a>
<a class="menu-item help float-right" href="http://readme.drone.io" target="_blank"></a>
<a class="menu-item user-name float-right" href="/profile">{{ "+"+user.login }}</a>
</header>
<div class="toolbar">
<div class="breadcrumb" style="position:relative;top:0px;">
<a href="/{{ repo.full_name }}/edit" class="icon icon-home"></a>
<a ng-href="/{{ repo.full_name }}">{{ repo.owner }} / {{ repo.name }}</a>
</div>
<div class="menu">
<a ng-href="/{{ repo.full_name }}/edit" class="nav-item settings float-right"></a>
<button ng-click="watch(repo)" ng-if="!repo.starred" class="nav-item star float-right"></button>
<button ng-click="unwatch(repo)" ng-if="repo.starred" class="nav-item unstar float-right"></button>
</div>
</div>
<article>
<section style="padding:30px; background-color:#EF5350;">
<button ng-click="delete(repo.full_name)" style="color:rgba(255,255,255,0.9);
text-transform: uppercase;
text-decoration: none;
border: 1px solid rgba(255,255,255,0.9);
padding: 10px;
background:transparent;
display:inline-block;
cursor:pointer;
margin-right: 10px;">Delete</button>
<span style="color:rgba(255,255,255,0.9);font-size:16px;">Warning: this action cannot be undone.</span>
</section>
</article>

View file

@ -1,95 +0,0 @@
<header>
<a class="logo float-left" href="/"></a>
<a class="menu-item settings float-right" href="/profile"></a>
<a class="menu-item users float-right" href="/users" ng-if="user.admin"></a>
<a class="menu-item help float-right" href="http://readme.drone.io" target="_blank"></a>
<a class="menu-item user-name float-right" href="/profile">{{ "+"+user.login }}</a>
</header>
<div class="toolbar">
<div class="breadcrumb" style="position:relative;top:0px;">
<a href="/{{ repo.full_name }}" class="icon icon-home"></a>
<a ng-href="/{{ repo.full_name }}">{{ repo.owner }} / {{ repo.name }}</a>
</div>
<div class="menu">
<a href="settings.html" class="icon icon-settings"></a>
<a ng-href="/{{ repo.full_name }}/edit" class="nav-item settings float-right"></a>
<button ng-click="watch(repo)" ng-if="!repo.starred" class="nav-item star float-right"></button>
<button ng-click="unwatch(repo)" ng-if="repo.starred" class="nav-item unstar float-right"></button>
</div>
</div>
<article>
<section>
<h2>Settings</h2>
<div class="row">
<div>Post Commit Hooks</div>
<div>
<input id="post_commits" type="checkbox" hidden="hidden" ng-model="repo.hooks.push" ng-change="save(repo)" />
<label for="post_commits" class="switch"></label>
</div>
</div>
<div class="row">
<div>Pull Request Hooks</div>
<div>
<input id="pull_requests" type="checkbox" hidden="hidden" ng-model="repo.hooks.pull_request" ng-change="save(repo)" />
<label for="pull_requests" class="switch"></label>
</div>
</div>
<a class="row" ng-href="{{ repo.full_name }}/edit/env">
<div>Private Variables</div>
<div>
Inject private variables into your build environment
</div>
</a>
<a class="row" ng-href="{{ repo.full_name }}/delete">
<div>Delete</div>
<div>Delete this repository and its build history</div>
</a>
</section>
<section ng-if="user.admin">
<h2>Admin settings</h2>
<div class="row">
<div>Trusted (Evelvate Privilege)</div>
<div>
<input id="trusted" type="checkbox" hidden="hidden" ng-model="repo.trusted" ng-change="save(repo)" />
<label for="trusted" class="switch"></label>
</div>
</div>
<div class="row">
<div>Timeout in minutes</div>
<div>
<input type="range" ng-model="repo.timeout" min="0" max="900" ng-blur="save(repo)" />
<span class="slider-label">{{ repo.timeout }} minutes</span>
</div>
</div>
</section>
<section>
<h2>Badges</h2>
<div class="row">
<div>Markdown</div>
<div>
<pre class="snippet">[![Build Status]({{ window.location.origin }}/api/badges/{{ repo.full_name }}/status.svg)]({{ window.location.origin }}/{{ repo.full_name }})</pre>
</div>
</div>
<div class="row">
<div>CCMenu</div>
<div>
<pre class="snippet">{{ window.location.origin }}/api/badges/{{ repo.full_name }}/cc.xml</pre>
</div>
</div>
</section>
<section>
<h2>Public Key</h2>
<div>
<pre class="snippet snippet-padding">{{ repo.keypair.public }}</pre>
</div>
</section>
</article>

View file

@ -1,41 +0,0 @@
<header>
<a class="logo float-left" href="/"></a>
<a class="menu-item settings float-right" href="/profile"></a>
<a class="menu-item users float-right" href="/users" ng-if="user.admin"></a>
<a class="menu-item help float-right" href="http://readme.drone.io" target="_blank"></a>
<a class="menu-item user-name float-right" href="/profile">{{ "+"+user.login }}</a>
</header>
<div class="toolbar">
<div class="breadcrumb" style="position:relative;top:0px;">
<a href="/" class="icon icon-home"></a>
<a href="#">Users</a>
</div>
</div>
<article>
<section>
<form style="padding:30px">
<input type="text" ng-model="login" placeholder="i.e. octocat" style="font-size:14px;padding:10px 20px;width:400px;border: 1px solid #d9d9d9;outline:none;"/>
<button ng-click="add(login)" style="display: inline-block;background:#EEE;font-size:14px; padding:0px 20px;text-transform:uppercase;cursor:pointer;color:#616161;height:39px;line-height:41px;margin-left:10px;">Add User</button>
</form>
</section>
<section>
<div class="row row-user" ng-repeat="user in users">
<div>
<img ng-src="{{ user.gravatar_id | gravatar }}" />
</div>
<div>
<h3>{{ user.login }} <small ng-if="user.admin">Admin</small></h3>
<p>{{ user.email }}</p>
<button ng-click="toggle(user)" ng-class="{'btn-admin':true, 'btn-checked': user.admin}"></button>
<button ng-click="remove(user)" class="btn-remove"></button>
</div>
</div>
</section>
</article>

View file

@ -0,0 +1,36 @@
<article>
<section>
<form style="padding:30px">
<input type="text" ng-model="login" placeholder="i.e. octocat"
style="font-size:14px;padding:10px 20px;width:400px;border: 1px solid #d9d9d9;outline:none;"/>
<button ng-click="add(login)"
style="display: inline-block;background:#EEE;font-size:14px; padding:0px 20px;text-transform:uppercase;cursor:pointer;color:#616161;height:39px;line-height:41px;margin-left:10px;">
Add User
</button>
</form>
</section>
<section>
<div class="row row-user" ng-repeat="user in users">
<div>
<img ng-src="{{ user.gravatar_id | gravatar }}"/>
</div>
<div>
<h3>{{ user.login }}
<small ng-if="user.admin">Admin</small>
</h3>
<p>{{ user.email }}</p>
<button ng-click="toggle(user)" ng-class="{'btn-admin':true, 'btn-checked': user.admin}">
<i class="material-icons md-18">account_circle</i>
</button>
<button ng-click="remove(user)" class="btn-remove">
<i class="material-icons md-18">delete</i>
</button>
</div>
</div>
</section>
</article>

View file

@ -0,0 +1,6 @@
<div class="breadcrumb" style="position:relative;top:0px;">
<a href="/" class="icon icon-home">
<i class="material-icons md-18">home</i>
</a>
<a href="#">Users</a>
</div>

File diff suppressed because it is too large Load diff