Start on mobilification of repo view

This commit is contained in:
Joseph Schorr 2015-04-20 17:42:33 -04:00
parent 79caf2dab2
commit a4cacd7307
31 changed files with 265 additions and 91 deletions

View file

@ -75,7 +75,7 @@
}
.co-nav-title .co-nav-title-content {
max-height: 50px;
height: 28px;
overflow: hidden;
text-overflow: ellipsis;
font-size: 22px;
@ -329,6 +329,21 @@
padding: 10px;
}
@media (max-width: 767px) {
.co-panel > .co-panel-body {
padding: 0px;
padding-top: 10px;
padding-bottom: 10px;
}
.co-panel > .panel-body {
padding: 0px;
padding-top: 10px;
padding-bottom: 10px;
}
}
.co-panel .co-panel-button-bar {
margin-top: 10px;
padding-top: 10px;
@ -982,6 +997,12 @@
padding-left: 28px;
}
@media (max-width: 767px) {
.co-table tr.indented-row td:first-child {
padding-left: 0px;
}
}
.co-table .mobile-row {
border-bottom: 2px solid #eee;
padding-bottom: 10px;

View file

@ -23,3 +23,17 @@
.repo-panel-settings-element .panel-section .btn .fa {
margin-right: 6px;
}
.repo-panel-settings-element .delete-btn {
float: right;
margin-top: -7px !important;
}
@media (max-width: 767px) {
.repo-panel-settings-element .delete-btn {
float: none;
margin-top: 0px !important;
margin-bottom: 20px;
display: block;
}
}

View file

@ -83,4 +83,33 @@
.repo-panel-tags-element .tag-image-history-item .fa-circle-o {
margin-right: 2px;
}
@media (max-width: 767px) {
.repo-panel-tags-element .tag-span i {
display: none;
}
.repo-panel-tags-element .co-filter-box {
display: block;
float: none;
margin-top: 10px;
margin-bottom: 20px;
}
.repo-panel-tags-element .co-filter-box input {
width: 100%;
}
.repo-panel-tags-element .co-checked-actions .btn i {
font-size: 16px;
width: 18px;
text-align: center;
display: inline-block;
}
.repo-panel-tags-element .co-checked-actions .btn .text {
display: none;
}
}

View file

@ -25,7 +25,7 @@
}
.logs-view-element .manager-header {
padding-bottom: 72px;
padding-bottom: 82px;
}
}

View file

@ -18,6 +18,26 @@
height: 40px;
}
.repo-tag-history-element .co-filter-box {
float: right;
}
@media (max-width: 767px) {
.repo-tag-history-element .history-list {
margin: 10px;
}
.repo-tag-history-element .history-entry .history-text {
height: 60px;
}
.repo-tag-history-element .co-filter-box {
float: none;
display: block;
}
}
.repo-tag-history-element .history-entry.filtered-mismatch {
margin-top: 10px;
}

View file

@ -12,4 +12,10 @@
left: -2px;
font-size: 16px;
color: #E8BB03;
}
.repository-permissions-table .mobile-add-row {
margin-top: 6px;
padding-top: 10px;
border-top: 2px solid #eee;
}

View file

@ -0,0 +1,52 @@
.role-group .btn {
width: 90px;
position: relative;
text-align: left;
}
.role-group .btn .caret {
position: absolute;
top: 15px;
right: 7px;
}
.role-group .role-help-text {
font-size: 12px;
color: #ccc;
margin-top: 4px;
margin-bottom: 2px;
}
.role-group .btn {
border-left: 4px solid #ccc;
}
.role-group .btn.success {
border-left-color: #5cb85c;
}
.role-group .btn.primary {
border-left-color: #337ab7;
}
.role-group li a {
vertical-align: middle;
}
.role-group li a:before {
content: "";
border-radius: 50%;
width: 10px;
height: 10px;
background: #ccc;
display: inline-block;
margin-right: 6px;
}
.role-group li.success a:before {
background-color: #5cb85c;
}
.role-group li.primary a:before {
background-color: #337ab7;
}

View file

@ -47,4 +47,4 @@
.repository-view .tag-span {
white-space: nowrap;
}
}

View file

@ -10,7 +10,7 @@
<div class="image-section">
<i class="fa fa-code section-icon" bs-tooltip="tooltip.title" data-title="Full Image ID"></i>
<span class="section-info">
<a class="image-link" ng-href="{{ tracker.imageLink(image) }}">
<a class="current-image-link" ng-href="{{ tracker.imageLink(image) }}">
{{ imageData.id }}
</a>
</span>

View file

@ -58,7 +58,9 @@
<span class="entity-reference block-reference" entity="prototype.delegate" namespace="organization.name" avatar-size="24"></span>
</td>
<td>
<span class="role-group" current-role="prototype.role" role-changed="setRole(role, prototype)" roles="roles"></span>
<span class="role-group" current-role="prototype.role"
role-changed="setRole(role, prototype)"
roles="repoRoles"></span>
</td>
<td class="options-col">
<span class="cor-options-menu">
@ -111,7 +113,8 @@
<tr>
<td>Permission:</td>
<td>
<span class="role-group" current-role="newRole" role-changed="setRoleForNew(role)" roles="roles"></span>
<span class="role-group" current-role="newRole" role-changed="setRoleForNew(role)"
roles="repoRoles"></span>
</td>
</tr>
<tr>

View file

@ -1,7 +1,7 @@
<div class="repo-tag-history-element">
<div class="cor-loader" ng-if="!historyEntries"></div>
<span class="co-filter-box" style="float:right">
<span class="co-filter-box">
<input class="form-control" type="text" ng-model="filter" placeholder="Filter History...">
</span>

View file

@ -41,18 +41,20 @@
style="min-width: 85px;">
<a href="javascript:void(0)" ng-click="orderBy('id')">Build ID</a>
</td>
<td ng-class="tablePredicateClass('commit_sha', options.predicate, options.reverse)"
<td class="hidden-xs"
ng-class="tablePredicateClass('commit_sha', options.predicate, options.reverse)"
style="min-width: 115px">
<a href="javascript:void(0)" ng-click="orderBy('commit_sha')">Triggered By</a>
</td>
<td ng-class="tablePredicateClass('started_datetime', options.predicate, options.reverse)" style="min-width: 120px;">
<a href="javascript:void(0)" ng-click="orderBy('started_datetime')">Date Started</a>
</td>
<td ng-class="tablePredicateClass('tags', options.predicate, options.reverse)"
<td class="hidden-xs"
ng-class="tablePredicateClass('tags', options.predicate, options.reverse)"
style="min-width: 66px;">
<a href="javascript:void(0)" ng-click="orderBy('tags')">Tags</a>
</td>
<td class="options-col"></td>
<td class="options-col hidden-xs"></td>
</thead>
<tr ng-repeat="build in fullBuilds">
@ -60,11 +62,11 @@
<td>
<a href="/repository/{{ repository.namespace }}/{{ repository.name }}/build/{{ build.id }}">{{ build.id.substr(0, 8) }}</a>
</td>
<td>
<td class="hidden-xs">
<div class="triggered-build-description" build="build"></div>
</td>
<td>{{ build.started | amCalendar }}</td>
<td>
<td class="hidden-xs">
<span class="building-tag" ng-repeat="tag in build.building_tags">
<span class="tag-span"><i class="fa fa-tag"></i>{{ tag }}</span>
</span>
@ -113,7 +115,7 @@
</div>
<!-- Triggers list -->
<table class="co-table" ng-if="triggers.length">
<table class="cor-table" ng-if="triggers.length">
<thead>
<td>Trigger Name</td>
<td>Dockerfile Location</td>

View file

@ -50,8 +50,7 @@
<!-- Delete Repository -->
<div class="panel-body panel-section">
<div class="co-alert co-alert-danger">
<button class="btn btn-danger" style="float: right; margin-top: -7px;"
ng-click="askDelete()">
<button class="btn btn-danger delete-btn" ng-click="askDelete()">
<i class="fa fa-trash"></i>
Delete Repository
</button>
@ -61,7 +60,7 @@
</div>
<!-- Build Status Badge -->
<div class="panel-body panel-section">
<div class="panel-body panel-section hidden-xs">
<!-- Status Image -->
<a ng-href="/repository/{{ repository.namespace }}/{{ repository.name }}">
<img ng-src="/repository/{{ repository.namespace }}/{{ repository.name }}/status?token={{ repository.status_token }}"

View file

@ -10,7 +10,7 @@
</div>
</div>
<h3 class="tab-header">Repository Tags</h3>
<h3 class="tab-header"><span class="hidden-xs">Repository </span>Tags</h3>
<!-- History view -->
<div class="repo-tag-history" repository="repository" filter="options.historyFilter"
@ -39,17 +39,17 @@
<span class="co-checked-actions" ng-if="checkedTags.checked.length">
<a href="javascript:void(0)" class="btn btn-default" ng-click="setTab('changes')">
<i class="fa fa-code-fork"></i> Visualize
<i class="fa fa-code-fork"></i><span class="text">Visualize</span>
</a>
<a href="javascript:void(0)" class="btn btn-default"
ng-click="showHistory(true, getTagNames(checkedTags.checked))"
ng-if="repository.can_write">
<i class="fa fa-history"></i> View History
<i class="fa fa-history"></i><span class="text">View History</span>
</a>
<button class="btn btn-primary"
ng-click="askDeleteMultipleTags(checkedTags.checked)"
ng-if="repository.can_write">
<i class="fa fa-times"></i> Delete
<i class="fa fa-times"></i><span class="text">Delete</span>
</button>
</span>
@ -64,15 +64,18 @@
<td ng-class="tablePredicateClass('name', options.predicate, options.reverse)">
<a href="javascript:void(0)" ng-click="orderBy('name')">Tag</a>
</td>
<td ng-class="tablePredicateClass('last_modified_datetime', options.predicate, options.reverse)"
<td class="hidden-xs"
ng-class="tablePredicateClass('last_modified_datetime', options.predicate, options.reverse)"
style="min-width: 120px;">
<a href="javascript:void(0)" ng-click="orderBy('last_modified_datetime')">Last Modified</a>
</td>
<td ng-class="tablePredicateClass('size', options.predicate, options.reverse)"
<td class="hidden-xs"
ng-class="tablePredicateClass('size', options.predicate, options.reverse)"
style="min-width: 62px;">
<a href="javascript:void(0)" ng-click="orderBy('size')">Size</a>
</td>
<td ng-class="tablePredicateClass('image_id', options.predicate, options.reverse)"
<td class="hidden-xs"
ng-class="tablePredicateClass('image_id', options.predicate, options.reverse)"
colspan="{{ imageTracks.length + 1 }}"
style="min-width: 120px;">
<a href="javascript:void(0)" ng-click="orderBy('image_id')">Image</a>
@ -87,15 +90,15 @@
ng-class="checkedTags.isChecked(tag, checkedTags.checked) ? 'checked' : ''">
<td><span class="cor-checkable-item" controller="checkedTags" item="tag"></span></td>
<td><span class="tag-span"><i class="fa fa-tag"></i> {{ tag.name }}</span></td>
<td>
<td class="hidden-xs">
<span am-time-ago="tag.last_modified" ng-if="tag.last_modified"></span>
<span ng-if="!tag.last_modified">Unknown</span>
</td>
<td>{{ tag.size | bytes }}</td>
<td class="image-id-col">
<td class="hidden-xs">{{ tag.size | bytes }}</td>
<td class="hidden-xs image-id-col">
<span class="image-link" repository="repository" image-id="tag.image_id"></span>
</td>
<td class="image-track" ng-repeat="it in imageTracks">
<td class="hidden-xs image-track" ng-repeat="it in imageTracks">
<span class="image-track-dot" ng-if="it.image_id == tag.image_id"
ng-style="{'borderColor': it.color}" ng-click="selectTrack(it)"></span>
<span class="image-track-line" ng-class="trackLineClass($parent.$index, it)"

View file

@ -15,9 +15,12 @@
<div class="empty" ng-if="!notifications.length">
<div class="empty-primary-msg">No notifications have been setup for this repository.</div>
<div class="empty-secondary-msg" ng-if="repository.can_write">
<div class="empty-secondary-msg hidden-xs" ng-if="repository.can_write">
Click the "Create Notification" button above to add a new notification for a repository event.
</div>
<div class="empty-secondary-msg visible-xs" ng-if="repository.can_write">
<a href="javascript:void(0)" ng-click="askCreateNotification()">Click here</a> to add a new notification for a repository event.
</div>
</div>
<table class="co-table permissions" ng-if="notifications.length">

View file

@ -3,14 +3,6 @@
resources="[permissionResources.team, permissionResources.user]"
error-message="'Could not load repository permissions'">
<table class="co-table no-lines permissions">
<thead>
<tr>
<td>Account Name</td>
<td style="width: 300px">Permissions</td>
<td class="options-col"></td>
</tr>
</thead>
<tr ng-show="!hasPermissions(permissionResources.team, permissionResources.user)">
<td colspan="3">
<div class="empty">
@ -35,7 +27,8 @@
</span>
</td>
<td class="user-permissions">
<span class="role-group" current-role="permission.role" role-changed="setRole(role, name, 'team')" roles="roles"></span>
<span class="role-group" current-role="permission.role"
role-changed="setRole(role, name, 'team')" roles="repoRoles"></span>
</td>
<td class="options-col">
@ -66,7 +59,8 @@
<td class="user-permissions">
<div class="btn-group btn-group-sm">
<span class="role-group" current-role="permission.role"
role-changed="setRole(role, permission.name, 'user')" roles="roles"></span>
role-changed="setRole(role, permission.name, 'user')"
roles="repoRoles"></span>
</div>
</td>
<td class="options-col">
@ -94,7 +88,8 @@
<td class="user-permissions">
<div class="btn-group btn-group-sm">
<span class="role-group" current-role="permission.role"
role-changed="setRole(role, permission.name, 'user')" roles="roles"></span>
role-changed="setRole(role, permission.name, 'user')"
roles="repoRoles"></span>
</div>
</td>
<td class="options-col">
@ -108,14 +103,15 @@
<tr class="add-row-spacer"><td colspan="3"></td></tr>
<tr class="add-row">
<tr class="add-row" ng-if-media="'(min-width: 768px)'">
<td id="add-entity-permission" class="admin-search">
<span class="entity-search" namespace="repository.namespace"
placeholder="'Select a ' + (repository.is_organization ? 'team or ' : '') + 'user...'"
current-entity="addPermissionInfo.entity"></span>
</td>
<td colspan="2">
<span class="role-group" current-role="addPermissionInfo.role" roles="roles"
<span class="role-group" current-role="addPermissionInfo.role"
roles="repoRoles"
role-changed="addPermissionInfo.role = role"></span>
<button class="btn btn-success" style="margin-left: 10px"
ng-disabled="!addPermissionInfo.role || !addPermissionInfo.entity"
@ -125,6 +121,20 @@
</td>
</tr>
</table>
<div class="mobile-add-row" ng-if-media="'(max-width: 767px)'">
<span class="entity-search" namespace="repository.namespace"
placeholder="'Select a ' + (repository.is_organization ? 'team or ' : '') + 'user...'"
current-entity="addPermissionInfo.entity"></span>
<span class="role-group" current-role="addPermissionInfo.role"
roles="repoRoles"
role-changed="addPermissionInfo.role = role"></span>
<button class="btn btn-success" style="margin-left: 10px"
ng-disabled="!addPermissionInfo.role || !addPermissionInfo.entity"
ng-click="addPermission()">
Add Permission
</button>
</div>
</div>
<!-- Grant Permission Confirm -->

View file

@ -115,7 +115,9 @@
</td>
<td>
<div class="btn-group btn-group-sm">
<span class="role-group" current-role="permission.role" roles="roles"
<span class="role-group"
current-role="permission.role"
roles="repoRoles"
read-only="true"></span>
</div>
</td>

View file

@ -1,6 +1,16 @@
<div class="btn-group btn-group-sm">
<button ng-repeat="role in roles"
type="button" class="btn" ng-click="setRole(role.id)"
ng-class="(currentRole == role.id) ? ('active btn-' + role.kind) : 'btn-default'"
ng-disabled="readOnly">{{ role.title }}</button>
<div class="dropdown" style="text-align: left;">
<button class="btn btn-default" ng-class="getRoleInfo(currentRole).kind" data-toggle="dropdown">
<span ng-if="currentRole" class="role-title">{{ getRoleInfo(currentRole).title }}</span>
<span ng-if="!currentRole">(Select)</span>
<span class="caret"></span>
</button>
<ul class="dropdown-menu pull-right">
<li ng-repeat="roleInfo in fullRoles" ng-class="roleInfo.kind">
<a href="javascript:void(0)" ng-click="setRole(roleInfo.id)">{{ roleInfo.title }}
<div class="role-help-text">{{ roleInfo.description }}</div>
</a>
</li>
</ul>
</div>
</div>

View file

@ -51,7 +51,8 @@
</div>
<div class="col-sm-5 col-md-4 control-col" ng-show="organization.is_admin">
<span class="role-group" current-role="team.role" role-changed="setRole(role, team.name)" roles="teamRoles"></span>
<span class="role-group" current-role="team.role"
role-changed="setRole(role, team.name)" roles="teamRoles"></span>
<span class="cor-options-menu">
<span class="cor-option" option-click="askDeleteTeam(team.name)">

View file

@ -754,7 +754,10 @@ angular.module("core-ui", [])
displayer.removeAttr('ng-repeat');
}
displayer.append(headers[idx].clone(true).addClass('mobile-col-header'));
if (idx < headers.length) {
displayer.append(headers[idx].clone(true).addClass('mobile-col-header'));
}
displayer.append(cloneWithAttr(td, 'div', true).addClass('mobile-col-value'));
div.append(displayer);
});

View file

@ -18,12 +18,6 @@ angular.module('quay').directive('prototypeManager', function () {
$scope.clearCounter = 0;
$scope.newForWholeOrg = true;
$scope.roles = [
{ 'id': 'read', 'title': 'Read', 'kind': 'success' },
{ 'id': 'write', 'title': 'Write', 'kind': 'success' },
{ 'id': 'admin', 'title': 'Admin', 'kind': 'primary' }
];
$scope.setRole = function(role, prototype) {
var params = {
'orgname': $scope.organization.name,

View file

@ -28,13 +28,6 @@ angular.module('quay').directive('repositoryPermissionsTable', function () {
'repository': '=repository'
},
controller: function($scope, $element, ApiService, Restangular, UtilService) {
// TODO(jschorr): move this to a service.
$scope.roles = [
{ 'id': 'read', 'title': 'Read', 'kind': 'success' },
{ 'id': 'write', 'title': 'Write', 'kind': 'success' },
{ 'id': 'admin', 'title': 'Admin', 'kind': 'primary' }
];
$scope.permissionResources = {'team': {}, 'user': {}};
$scope.permissionCache = {};
$scope.permissions = {};

View file

@ -14,12 +14,6 @@ angular.module('quay').directive('repositoryTokensTable', function () {
'hasTokens': '=hasTokens'
},
controller: function($scope, $element, ApiService, Restangular, UtilService) {
$scope.roles = [
{ 'id': 'read', 'title': 'Read', 'kind': 'success' },
{ 'id': 'write', 'title': 'Write', 'kind': 'success' },
{ 'id': 'admin', 'title': 'Admin', 'kind': 'primary' }
];
$scope.hasTokens = false;
var loadTokens = function() {

View file

@ -15,13 +15,6 @@ angular.module('quay').directive('robotsManager', function () {
controller: function($scope, $element, ApiService, $routeParams, CreateService, Config) {
$scope.ROBOT_PATTERN = ROBOT_PATTERN;
// TODO(jschorr): move this to a service.
$scope.roles = [
{ 'id': 'read', 'title': 'Read', 'kind': 'success' },
{ 'id': 'write', 'title': 'Write', 'kind': 'success' },
{ 'id': 'admin', 'title': 'Admin', 'kind': 'primary' }
];
$scope.robots = null;
$scope.loading = false;
$scope.shownRobot = null;

View file

@ -10,12 +10,14 @@ angular.module('quay').directive('roleGroup', function () {
transclude: false,
restrict: 'C',
scope: {
'roles': '=roles',
'roles': '@roles',
'currentRole': '=currentRole',
'readOnly': '=readOnly',
'roleChanged': '&roleChanged'
},
controller: function($scope, $element) {
controller: function($scope, $element, RolesService) {
$scope.fullRoles = RolesService[$scope.roles];
$scope.setRole = function(role) {
if ($scope.currentRole == role) { return; }
if ($scope.roleChanged) {
@ -24,6 +26,14 @@ angular.module('quay').directive('roleGroup', function () {
$scope.currentRole = role;
}
};
$scope.getRoleInfo = function(role) {
var found = null;
$scope.fullRoles.forEach(function(r) {
if (r.id == role) { found = r; }
});
return found;
};
}
};
return directiveDefinitionObject;

View file

@ -97,12 +97,6 @@
$scope.TEAM_PATTERN = TEAM_PATTERN;
$rootScope.title = 'Loading...';
$scope.teamRoles = [
{ 'id': 'member', 'title': 'Member', 'kind': 'default' },
{ 'id': 'creator', 'title': 'Creator', 'kind': 'success' },
{ 'id': 'admin', 'title': 'Admin', 'kind': 'primary' }
];
$scope.setRole = function(role, teamname) {
var previousRole = $scope.organization.teams[teamname].role;
$scope.organization.teams[teamname].role = role;

View file

@ -110,12 +110,6 @@
}, ApiService.errorDisplay('Cannot change permission'));
};
$scope.roles = [
{ 'id': 'read', 'title': 'Read', 'kind': 'success' },
{ 'id': 'write', 'title': 'Write', 'kind': 'success' },
{ 'id': 'admin', 'title': 'Admin', 'kind': 'primary' }
];
$scope.setRole = function(role, entityName, kind) {
var permission = $scope.permissions[kind][entityName];
var currentRole = permission.role;

View file

@ -0,0 +1,20 @@
/**
* Service which defines the various role groups.
*/
angular.module('quay').factory('RolesService', [function() {
var roleService = {};
roleService.repoRoles = [
{ 'id': 'read', 'title': 'Read', 'kind': 'success', 'description': 'Can view and pull from the repository' },
{ 'id': 'write', 'title': 'Write', 'kind': 'success', 'description': 'Can view, pull and push to the repository' },
{ 'id': 'admin', 'title': 'Admin', 'kind': 'primary', 'description': 'Full admin access, pull and push on the repository' }
];
roleService.teamRoles = [
{ 'id': 'member', 'title': 'Member', 'kind': 'default', 'description': 'Inherits all permissions of the team' },
{ 'id': 'creator', 'title': 'Creator', 'kind': 'success', 'description': 'Member and can create new repositories' },
{ 'id': 'admin', 'title': 'Admin', 'kind': 'primary', 'description': 'Full admin access to the organization' }
];
return roleService;
}]);

View file

@ -37,7 +37,8 @@
</div>
<div class="col-sm-5 col-md-4 control-col" ng-show="organization.is_admin">
<span class="role-group" current-role="team.role" role-changed="setRole(role, team.name)" roles="teamRoles"></span>
<span class="role-group" current-role="team.role" role-changed="setRole(role, team.name)"
roles="teamRoles"></span>
<button class="btn btn-sm btn-danger" ng-click="askDeleteTeam(team.name)">Delete</button>
</div>
</div>

View file

@ -111,7 +111,9 @@
</span>
</td>
<td class="user-permissions">
<span class="role-group" current-role="permission.role" role-changed="setRole(role, name, 'team')" roles="roles"></span>
<span class="role-group" current-role="permission.role"
role-changed="setRole(role, name, 'team')"
roles="repoRoles"></span>
</td>
<td>
<span class="delete-ui" delete-title="'Delete Permission'" perform-delete="deleteRole(name, 'team')"></span>
@ -127,7 +129,8 @@
</td>
<td class="user-permissions">
<div class="btn-group btn-group-sm">
<span class="role-group" current-role="permission.role" role-changed="setRole(role, name, 'user')" roles="roles"></span>
<span class="role-group" current-role="permission.role"
role-changed="setRole(role, name, 'user')" roles="repoRoles"></span>
</div>
</td>
<td>