- Switch font to Source Sans Pro, like CoreUpdate

- Add support for the new cor-tabs
- Add support for title-based layouts
- Switch super user layout to the new tabs UI in prep for adding setup support
This commit is contained in:
Joseph Schorr 2014-12-22 15:13:23 -05:00
parent 914df9af1a
commit 1f9f4ef26b
14 changed files with 345 additions and 170 deletions

View file

@ -18,9 +18,9 @@ EXTERNAL_JS = [
] ]
EXTERNAL_CSS = [ EXTERNAL_CSS = [
'netdna.bootstrapcdn.com/font-awesome/4.1.0/css/font-awesome.css', 'netdna.bootstrapcdn.com/font-awesome/4.2.0/css/font-awesome.css',
'netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap.no-icons.min.css', 'netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap.no-icons.min.css',
'fonts.googleapis.com/css?family=Droid+Sans:400,700', 'fonts.googleapis.com/css?family=Source+Sans+Pro:400,700',
] ]
EXTERNAL_FONTS = [ EXTERNAL_FONTS = [

View file

@ -1,5 +1,5 @@
* { * {
font-family: 'Droid Sans', sans-serif; font-family: 'Source Sans Pro', sans-serif;
margin: 0; margin: 0;
} }
@ -116,6 +116,88 @@
box-shadow: 0px 2px 2px rgba(0, 0, 0, 0.4); box-shadow: 0px 2px 2px rgba(0, 0, 0, 0.4);
} }
.co-fx-text-shadow {
text-shadow: rgba(0, 0, 0, 1) 1px 1px 2px;
}
.co-nav-title {
height: 70px;
margin-top: -22px;
}
.co-nav-title .co-nav-title-content {
color: white;
text-align: center;
}
.co-tab-container {
padding: 0px;
}
.co-tabs {
margin: 0px;
padding: 0px;
width: 82px;
background-color: #e8f1f6;
border-right: 1px solid #DDE7ED;
display: table-cell;
float: none;
vertical-align: top;
}
.co-tab-content {
width: 100%;
display: table-cell;
float: none;
padding: 10px;
}
.co-tabs li {
list-style: none;
display: block;
border-bottom: 1px solid #DDE7ED;
}
.co-tabs li.active {
background-color: white;
border-right: 1px solid white;
margin-right: -1px;
}
.co-tabs li a {
display: block;
width: 82px;
height: 82px;
line-height: 82px;
text-align: center;
font-size: 36px;
color: gray;
}
.co-tabs li.active a {
color: black;
}
.co-main-content-panel {
margin-bottom: 20px;
background-color: #fff;
border: 1px solid transparent;
padding: 10px;
-webkit-box-shadow: 0px 2px 2px rgba(0, 0, 0, 0.4);
-moz-box-shadow: 0px 2px 2px rgba(0, 0, 0, 0.4);
-ms-box-shadow: 0px 2px 2px rgba(0, 0, 0, 0.4);
-o-box-shadow: 0px 2px 2px rgba(0, 0, 0, 0.4);
box-shadow: 0px 2px 2px rgba(0, 0, 0, 0.4);
}
.co-tab-panel {
padding: 0px;
}
.main-panel { .main-panel {
margin-bottom: 20px; margin-bottom: 20px;
background-color: #fff; background-color: #fff;

View file

@ -0,0 +1 @@
<div class="co-tab-content tab-content col-md-11" ng-transclude></div>

View file

@ -0,0 +1,3 @@
<div class="co-main-content-panel co-tab-panel co-fx-box-shadow-heavy">
<div class="container co-tab-container" ng-transclude></div>
</div>

View file

@ -0,0 +1,11 @@
<li ng-class="tabActive == 'true' ? 'active' : ''">
<a href="javascript:void(0)" data-title="{{ tabTitle }}"
data-toggle="tab"
data-target="{{ tabTarget }}"
data-placement="right"
data-container="body"
ng-click="tabInit()"
bs-tooltip>
<span ng-transclude/>
</a>
</li>

View file

@ -0,0 +1 @@
<ul class="co-tabs col-md-1" ng-transclude></ul>

View file

@ -0,0 +1,3 @@
<div class="col-lg-6 col-md-6 col-sm-6 col-xs-12">
<h2 class="co-nav-title-content co-fx-text-shadow" ng-transclude></h2>
</div>

View file

@ -0,0 +1 @@
<div class="col-lg-3 col-md-3 col-sm-3 col-xs-6" ng-transclude></div>

View file

@ -0,0 +1,2 @@
<div class="co-nav-title" ng-transclude></div>

View file

@ -126,7 +126,7 @@ function getMarkedDown(string) {
quayDependencies = ['ngRoute', 'chieffancypants.loadingBar', 'angular-tour', 'restangular', 'angularMoment', quayDependencies = ['ngRoute', 'chieffancypants.loadingBar', 'angular-tour', 'restangular', 'angularMoment',
'mgcrea.ngStrap', 'ngCookies', 'ngSanitize', 'angular-md5', 'pasvaz.bindonce', 'ansiToHtml', 'mgcrea.ngStrap', 'ngCookies', 'ngSanitize', 'angular-md5', 'pasvaz.bindonce', 'ansiToHtml',
'ngAnimate']; 'ngAnimate', 'core-ui'];
if (window.__config && window.__config.MIXPANEL_KEY) { if (window.__config && window.__config.MIXPANEL_KEY) {
quayDependencies.push('angulartics'); quayDependencies.push('angulartics');
@ -2226,7 +2226,7 @@ quayApp = angular.module('quay', quayDependencies, function($provide, cfpLoading
when('/user/', {title: 'Account Settings', description:'Account settings for ' + title, templateUrl: '/static/partials/user-admin.html', when('/user/', {title: 'Account Settings', description:'Account settings for ' + title, templateUrl: '/static/partials/user-admin.html',
reloadOnSearch: false, controller: UserAdminCtrl}). reloadOnSearch: false, controller: UserAdminCtrl}).
when('/superuser/', {title: 'Superuser Admin Panel', description:'Admin panel for ' + title, templateUrl: '/static/partials/super-user.html', when('/superuser/', {title: 'Superuser Admin Panel', description:'Admin panel for ' + title, templateUrl: '/static/partials/super-user.html',
reloadOnSearch: false, controller: SuperUserAdminCtrl}). reloadOnSearch: false, controller: SuperUserAdminCtrl, newLayout: true}).
when('/guide/', {title: 'Guide', description:'Guide to using private docker repositories on ' + title, when('/guide/', {title: 'Guide', description:'Guide to using private docker repositories on ' + title,
templateUrl: '/static/partials/guide.html', templateUrl: '/static/partials/guide.html',
controller: GuideCtrl}). controller: GuideCtrl}).
@ -6690,6 +6690,7 @@ quayApp.directive('ngBlur', function() {
}; };
}); });
quayApp.directive("filePresent", [function () { quayApp.directive("filePresent", [function () {
return { return {
restrict: 'A', restrict: 'A',
@ -6763,7 +6764,6 @@ quayApp.run(['$location', '$rootScope', 'Restangular', 'UserService', 'PlanServi
var changeTab = function(activeTab, opt_timeout) { var changeTab = function(activeTab, opt_timeout) {
var checkCount = 0; var checkCount = 0;
$timeout(function() { $timeout(function() {
if (checkCount > 5) { return; } if (checkCount > 5) { return; }
checkCount++; checkCount++;
@ -6827,6 +6827,8 @@ quayApp.run(['$location', '$rootScope', 'Restangular', 'UserService', 'PlanServi
$rootScope.pageClass = current.$$route.pageClass; $rootScope.pageClass = current.$$route.pageClass;
} }
$rootScope.newLayout = !!current.$$route.newLayout;
if (current.$$route.description) { if (current.$$route.description) {
$rootScope.description = current.$$route.description; $rootScope.description = current.$$route.description;
} else { } else {
@ -6842,6 +6844,7 @@ quayApp.run(['$location', '$rootScope', 'Restangular', 'UserService', 'PlanServi
// Setup deep linking of tabs. This will change the search field of the URL whenever a tab // Setup deep linking of tabs. This will change the search field of the URL whenever a tab
// is changed in the UI. // is changed in the UI.
$timeout(function() {
$('a[data-toggle="tab"]').on('shown.bs.tab', function (e) { $('a[data-toggle="tab"]').on('shown.bs.tab', function (e) {
var tabName = e.target.getAttribute('data-target').substr(1); var tabName = e.target.getAttribute('data-target').substr(1);
$rootScope.$apply(function() { $rootScope.$apply(function() {
@ -6862,6 +6865,7 @@ quayApp.run(['$location', '$rootScope', 'Restangular', 'UserService', 'PlanServi
if (activeTab) { if (activeTab) {
changeTab(activeTab); changeTab(activeTab);
} }
}, 100); // 100ms to make sure angular has rendered.
}); });
var initallyChecked = false; var initallyChecked = false;

View file

@ -2831,7 +2831,7 @@ function SuperUserAdminCtrl($scope, ApiService, Features, UserService) {
}, ApiService.errorDisplay('Cannot load system usage. Please contact support.')) }, ApiService.errorDisplay('Cannot load system usage. Please contact support.'))
} }
$scope.loadLogs = function() { $scope.loadUsageLogs = function() {
$scope.logsCounter++; $scope.logsCounter++;
}; };

104
static/js/core-ui.js Normal file
View file

@ -0,0 +1,104 @@
angular.module("core-ui", [])
.directive('corTitle', function() {
var directiveDefinitionObject = {
priority: 1,
templateUrl: '/static/directives/cor-title.html',
replace: true,
transclude: true,
restrict: 'C',
scope: {},
controller: function($rootScope, $scope, $element) {
}
};
return directiveDefinitionObject;
})
.directive('corTitleContent', function() {
var directiveDefinitionObject = {
priority: 1,
templateUrl: '/static/directives/cor-title-content.html',
replace: true,
transclude: true,
restrict: 'C',
scope: {},
controller: function($rootScope, $scope, $element) {
}
};
return directiveDefinitionObject;
})
.directive('corTitleLink', function() {
var directiveDefinitionObject = {
priority: 1,
templateUrl: '/static/directives/cor-title-link.html',
replace: true,
transclude: true,
restrict: 'C',
scope: {},
controller: function($rootScope, $scope, $element) {
}
};
return directiveDefinitionObject;
})
.directive('corTabPanel', function() {
var directiveDefinitionObject = {
priority: 1,
templateUrl: '/static/directives/cor-tab-panel.html',
replace: true,
transclude: true,
restrict: 'C',
scope: {},
controller: function($rootScope, $scope, $element) {
}
};
return directiveDefinitionObject;
})
.directive('corTabContent', function() {
var directiveDefinitionObject = {
priority: 2,
templateUrl: '/static/directives/cor-tab-content.html',
replace: true,
transclude: true,
restrict: 'C',
scope: {},
controller: function($rootScope, $scope, $element) {
}
};
return directiveDefinitionObject;
})
.directive('corTabs', function() {
var directiveDefinitionObject = {
priority: 3,
templateUrl: '/static/directives/cor-tabs.html',
replace: true,
transclude: true,
restrict: 'C',
scope: {},
controller: function($rootScope, $scope, $element) {
}
};
return directiveDefinitionObject;
})
.directive('corTab', function() {
var directiveDefinitionObject = {
priority: 4,
templateUrl: '/static/directives/cor-tab.html',
replace: true,
transclude: true,
restrict: 'C',
scope: {
'tabActive': '@tabActive',
'tabTitle': '@tabTitle',
'tabTarget': '@tabTarget',
'tabInit': '&tabInit'
},
controller: function($rootScope, $scope, $element) {
}
};
return directiveDefinitionObject;
});

View file

@ -1,34 +1,34 @@
<div class="container" quay-show="Features.SUPER_USERS && showInterface"> <div class="page-content" quay-show="Features.SUPER_USERS && showInterface">
<div class="alert alert-info"> <div class="cor-title">
This panel provides administrator access to <strong>super users of this installation of the registry</strong>. Super users can be managed in the configuration for this installation. <span class="cor-title-link"></span>
<span class="cor-title-content">Enterprise Registry Setup</span>
</div> </div>
<div class="row"> <div class="cor-tab-panel">
<!-- Side tabs --> <div class="cor-tabs">
<div class="col-md-2"> <!--<span class="cor-tab" tab-active="true" tab-title="Registry Settings" tab-target="#setup"
<ul class="nav nav-pills nav-stacked"> tab-init="loadConfig()">
<li class="active"> <i class="fa fa-cog"></i>
<a href="javascript:void(0)" data-toggle="tab" data-target="#users" ng-click="loadUsers()">Users</a> </span>-->
</li> <span class="cor-tab" tab-title="Manage Users" tab-target="#users" tab-init="loadUsers()">
<li> <i class="fa fa-group"></i>
<a href="javascript:void(0)" data-toggle="tab" data-target="#create-user">Create User</a> </span>
</li> <span class="cor-tab" tab-title="Container Usage" tab-target="#usage-counter" tab-init="getUsage()">
<li> <i class="fa fa-pie-chart"></i>
<a href="javascript:void(0)" data-toggle="tab" data-target="#usage-counter" ng-click="getUsage()">System Usage</a> </span>
</li> <span class="cor-tab" tab-title="Usage Logs" tab-target="#logs" tab-init="loadUsageLogs()">
<li> <i class="fa fa-bar-chart"></i>
<a href="javascript:void(0)" data-toggle="tab" data-target="#logs" ng-click="loadLogs()">System Logs</a> </span>
</li> <!--<span class="cor-tab" tab-title="Internal Logs and Debugging" tab-target="#debug">
</ul> <i class="fa fa-bug"></i>
</div> </span>-->
</div> <!-- /cor-tabs -->
<!-- Content --> <div class="cor-tab-content">
<div class="col-md-10">
<div class="tab-content">
<!-- Logs tab --> <!-- Logs tab -->
<div id="logs" class="tab-pane"> <div id="logs" class="tab-pane">
<div class="logsView" makevisible="logsCounter" all-logs="true"></div> <div class="logsView" makevisible="logsCounter" all-logs="true"></div>
</div> </div> <!-- /logs tab-->
<!-- Usage tab --> <!-- Usage tab -->
<div id="usage-counter" class="tab-pane"> <div id="usage-counter" class="tab-pane">
@ -51,42 +51,7 @@
You are nearing the number of allowed deployed repositories. It might be time to think about You are nearing the number of allowed deployed repositories. It might be time to think about
upgrading your subscription by contacting <a href="mailto:sales@coreos.com">CoreOS Sales</a>. upgrading your subscription by contacting <a href="mailto:sales@coreos.com">CoreOS Sales</a>.
</div> </div>
</div> </div> <!-- /usage-counter tab-->
<!-- Create user tab -->
<div id="create-user" class="tab-pane">
<span class="quay-spinner" ng-show="creatingUser"></span>
<form name="createUserForm" ng-submit="createUser()" ng-show="!creatingUser">
<div class="form-group">
<label>Username</label>
<input class="form-control" type="text" ng-model="newUser.username" ng-pattern="/^[a-z0-9_]{4,30}$/" required>
</div>
<div class="form-group">
<label>Email address</label>
<input class="form-control" type="email" ng-model="newUser.email" required>
</div>
<button class="btn btn-primary" type="submit" ng-disabled="!createUserForm.$valid">Create User</button>
</form>
<div style="margin-top: 20px; padding-top: 20px; border-top: 1px solid #eee;" ng-show="createdUsers.length">
<table class="table">
<thead>
<th>Username</th>
<th>E-mail address</th>
<th>Temporary Password</th>
</thead>
<tr ng-repeat="created_user in createdUsers"
class="user-row">
<td>{{ created_user.username }}</td>
<td>{{ created_user.email }}</td>
<td>{{ created_user.password }}</td>
</tr>
</table>
</div>
</div>
<!-- Users tab --> <!-- Users tab -->
<div id="users" class="tab-pane active"> <div id="users" class="tab-pane active">
@ -124,7 +89,8 @@
</td> </td>
<td style="text-align: center;"> <td style="text-align: center;">
<i class="fa fa-ge fa-lg" ng-if="current_user.super_user" data-title="Super User" bs-tooltip></i> <i class="fa fa-ge fa-lg" ng-if="current_user.super_user" data-title="Super User" bs-tooltip></i>
<div class="dropdown" style="text-align: left;" ng-if="user.username != current_user.username && !current_user.super_user"> <div class="dropdown" style="text-align: left;"
ng-if="user.username != current_user.username && !current_user.super_user">
<button class="btn btn-default dropdown-toggle" data-toggle="dropdown"> <button class="btn btn-default dropdown-toggle" data-toggle="dropdown">
<i class="caret"></i> <i class="caret"></i>
</button> </button>
@ -145,13 +111,10 @@
</td> </td>
</tr> </tr>
</table> </table>
</div> <!-- /show if users -->
</div> </div> <!-- users-tab -->
</div> </div> <!-- /cor-tab-content -->
</div> </div> <!-- /cor-tab-panel -->
</div>
</div>
<!-- Modal message dialog --> <!-- Modal message dialog -->
<div class="modal fade" id="confirmDeleteUserModal"> <div class="modal fade" id="confirmDeleteUserModal">
@ -204,4 +167,5 @@
</div><!-- /.modal-dialog --> </div><!-- /.modal-dialog -->
</div><!-- /.modal --> </div><!-- /.modal -->
</div> </div> <!-- /page-content -->

View file

@ -96,10 +96,9 @@ mixpanel.init("{{ mixpanel_key }}", { track_pageview : false, debug: {{ is_debug
<body ng-class="pageClass + ' ' + (user.anonymous ? 'anon' : 'signedin')" class="co-img-bg-network"> <body ng-class="pageClass + ' ' + (user.anonymous ? 'anon' : 'signedin')" class="co-img-bg-network">
<div id="co-l-footer-wrapper"> <div id="co-l-footer-wrapper">
<nav class="navbar navbar-default header-bar co-m-navbar co-fx-box-shadow" role="navigation"></nav> <nav class="navbar navbar-default header-bar co-m-navbar co-fx-box-shadow" role="navigation"></nav>
<div id="padding-container"> <div id="padding-container">
<div id="co-l-view-container"> <div id="co-l-view-container">
<div class="main-panel co-fx-box-shadow-heavy"> <div ng-class="newLayout ? '' : 'main-panel co-fx-box-shadow-heavy'">
{% block body_content %} {% block body_content %}
{% endblock %} {% endblock %}