diff --git a/static/css/directives/repo-view/repo-panel-builds.css b/static/css/directives/repo-view/repo-panel-builds.css
index 03c3a6a57..3281cf272 100644
--- a/static/css/directives/repo-view/repo-panel-builds.css
+++ b/static/css/directives/repo-view/repo-panel-builds.css
@@ -10,20 +10,3 @@
margin-right: 6px;
vertical-align: middle;
}
-
-.repo-panel-builds .heading-title {
- font-size: 20px;
-}
-
-.repo-panel-builds .heading-controls {
- font-size: 14px;
- float: right;
-}
-
-.repo-panel-builds .heading-controls .btn {
- margin-top: -10px;
-}
-
-.repo-panel-builds .heading-controls .btn .fa {
- margin-right: 6px;
-}
diff --git a/static/css/directives/repo-view/repo-panel-settings.css b/static/css/directives/repo-view/repo-panel-settings.css
new file mode 100644
index 000000000..78e2c6b62
--- /dev/null
+++ b/static/css/directives/repo-view/repo-panel-settings.css
@@ -0,0 +1,25 @@
+.repo-panel-settings-element .panel-section {
+ padding: 20px;
+ border-bottom: 1px solid #eee;
+}
+
+.repo-panel-settings-element .lock-section {
+ position: relative;
+ padding-left: 80px;
+}
+
+.repo-panel-settings-element .lock-section .lock-icon {
+ position: absolute;
+ top: 10px;
+ left: 22px;
+ color: #ccc;
+ font-size: 46px;
+}
+
+.repo-panel-settings-element .panel-section .btn {
+ margin-top: 20px;
+}
+
+.repo-panel-settings-element .panel-section .btn .fa {
+ margin-right: 6px;
+}
diff --git a/static/css/directives/ui/repository-events-table.css b/static/css/directives/ui/repository-events-table.css
new file mode 100644
index 000000000..82909d022
--- /dev/null
+++ b/static/css/directives/ui/repository-events-table.css
@@ -0,0 +1,3 @@
+.repository-events-table-element .notification-row i.fa {
+ margin-right: 6px;
+}
\ No newline at end of file
diff --git a/static/css/pages/repo-view.css b/static/css/pages/repo-view.css
index 63fd8d0ed..5555ecb4b 100644
--- a/static/css/pages/repo-view.css
+++ b/static/css/pages/repo-view.css
@@ -22,3 +22,20 @@
.repository-view .tab-header-controls .btn .fa {
margin-right: 6px;
}
+
+.repository-view .heading-title {
+ font-size: 20px;
+}
+
+.repository-view .heading-controls {
+ font-size: 14px;
+ float: right;
+}
+
+.repository-view .heading-controls .btn {
+ margin-top: -10px;
+}
+
+.repository-view .heading-controls .btn .fa {
+ margin-right: 6px;
+}
diff --git a/static/directives/repo-view/repo-panel-settings.html b/static/directives/repo-view/repo-panel-settings.html
index 84a78a721..efe3c48eb 100644
--- a/static/directives/repo-view/repo-panel-settings.html
+++ b/static/directives/repo-view/repo-panel-settings.html
@@ -10,5 +10,86 @@
+
- Account Name
- Permissions
-
+ Account Name
+ Permissions
+
@@ -21,8 +21,13 @@
-
-
+
+
+
@@ -38,8 +43,12 @@
-
-
+
+
@@ -49,12 +58,10 @@
placeholder="'Select a ' + (repository.is_organization ? 'team or ' : '') + 'user...'"
current-entity="addPermissionInfo.entity">
-
+
-
-
-
Add Permission
diff --git a/static/directives/repository-tokens-table.html b/static/directives/repository-tokens-table.html
new file mode 100644
index 000000000..ddad74db5
--- /dev/null
+++ b/static/directives/repository-tokens-table.html
@@ -0,0 +1,35 @@
+
+
+
Note: Access tokens are
deprecated and will be removed in the near future.
Robot accounts are the recommended replacement.
+
+
+
+
+
\ No newline at end of file
diff --git a/static/js/directives/repo-view/repo-panel-settings.js b/static/js/directives/repo-view/repo-panel-settings.js
index fd7edfda3..961d028a6 100644
--- a/static/js/directives/repo-view/repo-panel-settings.js
+++ b/static/js/directives/repo-view/repo-panel-settings.js
@@ -11,7 +11,72 @@ angular.module('quay').directive('repoPanelSettings', function () {
scope: {
'repository': '=repository'
},
- controller: function($scope, $element, ApiService) {
+ controller: function($scope, $element, ApiService, Config) {
+ $scope.getBadgeFormat = function(format, repository) {
+ if (!repository) { return ''; }
+
+ var imageUrl = Config.getUrl('/repository/' + repository.namespace + '/' + repository.name + '/status');
+ if (!$scope.repository.is_public) {
+ imageUrl += '?token=' + repository.status_token;
+ }
+
+ var linkUrl = Config.getUrl('/repository/' + repository.namespace + '/' + repository.name);
+
+ switch (format) {
+ case 'svg':
+ return imageUrl;
+
+ case 'md':
+ return '[![Docker Repository on ' + Config.REGISTRY_TITLE_SHORT + '](' + imageUrl +
+ ' "Docker Repository on ' + Config.REGISTRY_TITLE_SHORT + '")](' + linkUrl + ')';
+
+ case 'asciidoc':
+ return 'image:' + imageUrl + '["Docker Repository on ' + Config.REGISTRY_TITLE_SHORT + '", link="' + linkUrl + '"]';
+ }
+
+ return '';
+ };
+
+ $scope.askDelete = function() {
+ bootbox.confirm('Are you sure you want delete this repository?', function(r) {
+ if (!r) { return; }
+ $scope.deleteRepo();
+ });
+ };
+
+ $scope.deleteRepo = function() {
+ var params = {
+ 'repository': $scope.repository.namespace + '/' + $scope.repository.name
+ };
+
+ ApiService.deleteRepository(null, params).then(function() {
+ setTimeout(function() {
+ document.location = '/repository/';
+ }, 100);
+ }, ApiService.errorDisplay('Could not delete repository'));
+ };
+
+
+ $scope.askChangeAccess = function(newAccess) {
+ bootbox.confirm('Are you sure you want to make this repository ' + newAccess + '?', function(r) {
+ if (!r) { return; }
+ $scope.changeAccess(newAccess);
+ });
+ };
+
+ $scope.changeAccess = function(newAccess) {
+ var visibility = {
+ 'visibility': newAccess
+ };
+
+ var params = {
+ 'repository': $scope.repository.namespace + '/' + $scope.repository.name
+ };
+
+ ApiService.changeRepoVisibility(visibility, params).then(function() {
+ $scope.repository.is_public = newAccess == 'public';
+ }, ApiService.errorDisplay('Could not change repository visibility'));
+ };
}
};
return directiveDefinitionObject;
diff --git a/static/js/directives/ui/external-notification-view.js b/static/js/directives/ui/external-notification-view.js
index 0e7fb4791..37b3f4c8a 100644
--- a/static/js/directives/ui/external-notification-view.js
+++ b/static/js/directives/ui/external-notification-view.js
@@ -1,5 +1,5 @@
/**
- * An element which displays controls and information about a defined external notification on
+ * DEPRECATED: An element which displays controls and information about a defined external notification on
* a repository.
*/
angular.module('quay').directive('externalNotificationView', function () {
diff --git a/static/js/directives/ui/repository-events-table.js b/static/js/directives/ui/repository-events-table.js
new file mode 100644
index 000000000..163baeb2d
--- /dev/null
+++ b/static/js/directives/ui/repository-events-table.js
@@ -0,0 +1,91 @@
+/**
+ * An element which displays a table of events on a repository and allows them to be
+ * edited.
+ */
+angular.module('quay').directive('repositoryEventsTable', function () {
+ var directiveDefinitionObject = {
+ priority: 0,
+ templateUrl: '/static/directives/repository-events-table.html',
+ replace: false,
+ transclude: true,
+ restrict: 'C',
+ scope: {
+ 'repository': '=repository'
+ },
+ controller: function($scope, $element, ApiService, Restangular, UtilService, ExternalNotificationData) {
+ $scope.showNewNotificationCounter = 0;
+
+ var loadNotifications = function() {
+ if (!$scope.repository || $scope.notificationsResource) { return; }
+ var params = {
+ 'repository': $scope.repository.namespace + '/' + $scope.repository.name
+ };
+
+ $scope.notificationsResource = ApiService.listRepoNotificationsAsResource(params).get(
+ function(resp) {
+ $scope.notifications = resp.notifications;
+ return $scope.notifications;
+ });
+ };
+
+ $scope.$watch('repository', loadNotifications);
+ loadNotifications();
+
+ $scope.handleNotificationCreated = function(notification) {
+ $scope.notifications.push(notification);
+ };
+
+ $scope.askCreateNotification = function() {
+ $scope.showNewNotificationCounter++;
+ };
+
+ $scope.getEventInfo = function(notification) {
+ return ExternalNotificationData.getEventInfo(notification.event);
+ };
+
+ $scope.getMethodInfo = function(notification) {
+ return ExternalNotificationData.getMethodInfo(notification.method);
+ };
+
+ $scope.deleteNotification = function(notification) {
+ var params = {
+ 'repository': $scope.repository.namespace + '/' + $scope.repository.name,
+ 'uuid': notification.uuid
+ };
+
+ ApiService.deleteRepoNotification(null, params).then(function() {
+ var index = $.inArray(notification, $scope.notifications);
+ if (index < 0) { return; }
+ $scope.notifications.splice(index, 1);
+ }, ApiService.errorDisplay('Cannot delete notification'));
+ };
+
+ $scope.showWebhookInfo = function(notification) {
+ var eventId = notification.event;
+ document.location = 'http://docs.quay.io/guides/notifications.html#webhook_' + eventId;
+ };
+
+ $scope.testNotification = function(notification) {
+ var params = {
+ 'repository': $scope.repository.namespace + '/' + $scope.repository.name,
+ 'uuid': notification.uuid
+ };
+
+ ApiService.testRepoNotification(null, params).then(function() {
+ bootbox.dialog({
+ "title": "Test Notification Queued",
+ "message": "A test version of this notification has been queued and should appear shortly",
+ "buttons": {
+ "close": {
+ "label": "Close",
+ "className": "btn-primary"
+ }
+ }
+ });
+ }, ApiService.errorDisplay('Could not issue test notification'));
+ };
+
+ }
+ };
+ return directiveDefinitionObject;
+});
\ No newline at end of file
diff --git a/static/js/directives/ui/repository-tokens-table.js b/static/js/directives/ui/repository-tokens-table.js
new file mode 100644
index 000000000..1828c4a05
--- /dev/null
+++ b/static/js/directives/ui/repository-tokens-table.js
@@ -0,0 +1,68 @@
+/**
+ * An element which displays a table of tokens on a repository and allows them to be
+ * edited.
+ */
+angular.module('quay').directive('repositoryTokensTable', function () {
+ var directiveDefinitionObject = {
+ priority: 0,
+ templateUrl: '/static/directives/repository-tokens-table.html',
+ replace: false,
+ transclude: true,
+ restrict: 'C',
+ scope: {
+ 'repository': '=repository',
+ '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() {
+ if (!$scope.repository || $scope.tokensResource) { return; }
+ var params = {
+ 'repository': $scope.repository.namespace + '/' + $scope.repository.name
+ };
+
+ $scope.tokensResource = ApiService.listRepoTokensAsResource(params).get(function(resp) {
+ $scope.tokens = resp.tokens;
+ $scope.hasTokens = Object.keys($scope.tokens).length >= 1;
+ }, ApiService.errorDisplay('Could not load access tokens'));
+ };
+
+ $scope.$watch('repository', loadTokens);
+ loadTokens();
+
+ $scope.deleteToken = function(tokenCode) {
+ var params = {
+ 'repository': $scope.repository.namespace + '/' + $scope.repository.name,
+ 'code': tokenCode
+ };
+
+ ApiService.deleteToken(null, params).then(function() {
+ delete $scope.tokens[tokenCode];
+ });
+ };
+
+ $scope.changeTokenAccess = function(tokenCode, newAccess) {
+ var role = {
+ 'role': newAccess
+ };
+
+ var params = {
+ 'repository': $scope.repository.namespace + '/' + $scope.repository.name,
+ 'code': tokenCode
+ };
+
+ ApiService.changeToken(role, params).then(function(updated) {
+ $scope.tokens[updated.code] = updated;
+ });
+ };
+ }
+ };
+ return directiveDefinitionObject;
+});
\ No newline at end of file