nifi-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From bbe...@apache.org
Subject [1/4] nifi-registry git commit: NIFIREG-30 - Add bucket side nav
Date Thu, 21 Dec 2017 15:46:50 GMT
Repository: nifi-registry
Updated Branches:
  refs/heads/master 2e35235d5 -> 6c48025c5


http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/6c48025c/nifi-registry-web-ui/src/main/webapp/images/registry-background-logo.svg
----------------------------------------------------------------------
diff --git a/nifi-registry-web-ui/src/main/webapp/images/registry-background-logo.svg b/nifi-registry-web-ui/src/main/webapp/images/registry-background-logo.svg
new file mode 100644
index 0000000..bd72815
--- /dev/null
+++ b/nifi-registry-web-ui/src/main/webapp/images/registry-background-logo.svg
@@ -0,0 +1,17 @@
+<!--
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You under the Apache License, Version 2.0
+    (the "License"); you may not use this file except in compliance with
+    the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+-->
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 142.71 182.73"><defs><style>.cls-1{fill:url(#linear-gradient);}.cls-2{fill:#6b8791;}.cls-3{fill:#8da4aa;}.cls-4{fill:#b0c1c6;}</style><linearGradient id="linear-gradient" x1="79.26" y1="128.13" x2="79.26" y2="78.82" gradientUnits="userSpaceOnUse"><stop offset="0.1" stop-color="#e2e6e8"/><stop offset="1" stop-color="#e2e6e8" stop-opacity="0"/></linearGradient></defs><title>Asset 5</title><g id="Layer_2" data-name="Layer 2"><g id="registryl-logo-mini"><polygon class="cls-1" points="54.6 128.13 54.6 78.82 103.91 78.82 54.6 128.13"/><polygon class="cls-2" points="0 182.73 0 133.42 49.31 133.42 0 182.73"/><rect class="cls-2" y="78.82" width="49.31" height="49.31" transform="translate(128.13 78.82) rotate(90)"/><path class="cls-2" d="M40.07,59.81l-.51-3c3.32-1.29,6.53-2.88,9.75-4.44V24.22H0V73.53H49.31V56.33C46.26,57.59,43.21,58.85,40.07,59.81ZM23.61,61.08A45.1,45.1,0,0,1,9.55,56.31c-2.21-1.17-
 .19-.72.86-.32a62.55,62.55,0,0,0,8,2.59,34.65,34.65,0,0,0,5.53.82Zm3,.34L27,59.48a33.79,33.79,0,0,0,7.72-1.07c.46-.12.9-.26,1.35-.4l.47,2.72A35.51,35.51,0,0,1,26.63,61.42Z"/><path class="cls-3" d="M64.48,46.82a40.43,40.43,0,0,1,21.43,2.29l8.78-3.72L75.42,0,30,19.27,45,54.45C51.31,51.46,57.47,48,64.48,46.82Z"/><path class="cls-3" d="M59.06,55.56c4.86-2.68,11.61-3.19,16.33-2.83,2.18.16,2.21-.35.11-.87a31.86,31.86,0,0,0-10.92-.42c-6.44.92-12.3,3.72-18.29,6.12l3,7.09h0C49.42,62.91,52.37,59.24,59.06,55.56Z"/><path class="cls-4" d="M102.44,61.87a36.29,36.29,0,0,1,5.42,13L142.71,40,107.84,5.13,73,40l7.38,7.39C89.2,49.47,97.4,54.46,102.44,61.87Z"/></g></g></svg>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/6c48025c/nifi-registry-web-ui/src/main/webapp/nf-registry.html
----------------------------------------------------------------------
diff --git a/nifi-registry-web-ui/src/main/webapp/nf-registry.html b/nifi-registry-web-ui/src/main/webapp/nf-registry.html
index 21eaffa..6b519c1 100644
--- a/nifi-registry-web-ui/src/main/webapp/nf-registry.html
+++ b/nifi-registry-web-ui/src/main/webapp/nf-registry.html
@@ -75,11 +75,14 @@ limitations under the License.
                 <div id="current-user" matTooltip="{{nfRegistryService.currentUser.identity}}">{{nfRegistryService.currentUser.identity}}</div>
                 <a id="logout-link-container" *ngIf="nfRegistryService.currentUser.canLogout" class="link" (click)="logout()">logout</a>
             </div>
-            <button mat-ripple *ngIf="nfRegistryService.currentUser.resourcePermissions.anyTopLevelResource.canRead && nfRegistryService.perspective === 'explorer'" mat-icon-button
+            <div id="nifi-registry-documentation" class="pad-right-sm">
+                <a [matTooltip]="'Help'" href="{{nfRegistryService.documentation.link}}" target="_blank"><i class="fa fa-question-circle help-icon" aria-hidden="true"></i></a>
+            </div>
+            <button [matTooltip]="'Settings'" mat-ripple *ngIf="nfRegistryService.currentUser.resourcePermissions.anyTopLevelResource.canRead && nfRegistryService.perspective === 'explorer'" mat-icon-button
                     routerLink="/nifi-registry/administration/workflow">
                 <i class="fa fa-wrench" aria-hidden="true"></i>
             </button>
-            <button [matTooltip]="'Close administration.'" mat-ripple *ngIf="nfRegistryService.perspective === 'administration'" mat-mini-fab
+            <button [matTooltip]="'Close settings.'" mat-ripple *ngIf="nfRegistryService.perspective === 'administration'" mat-mini-fab
                     routerLink="/nifi-registry/explorer/{{(nfRegistryService.explorerViewType) ? nfRegistryService.explorerViewType : 'grid-list'}}">
                 <mat-icon color="primary">close</mat-icon>
             </button>

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/6c48025c/nifi-registry-web-ui/src/main/webapp/nf-registry.module.js
----------------------------------------------------------------------
diff --git a/nifi-registry-web-ui/src/main/webapp/nf-registry.module.js b/nifi-registry-web-ui/src/main/webapp/nf-registry.module.js
index b250d13..41af1a5 100644
--- a/nifi-registry-web-ui/src/main/webapp/nf-registry.module.js
+++ b/nifi-registry-web-ui/src/main/webapp/nf-registry.module.js
@@ -30,13 +30,15 @@ var NfRegistryAdministration = require('nifi-registry/components/administration/
 var NfRegistryUsersAdministration = require('nifi-registry/components/administration/users/nf-registry-users-administration.js');
 var NfRegistryAddUser = require('nifi-registry/components/administration/users/dialogs/add-user/nf-registry-add-user.js');
 var NfRegistryCreateNewGroup = require('nifi-registry/components/administration/users/dialogs/create-new-group/nf-registry-create-new-group.js');
+var NfRegistryEditBucketPolicy = require('nifi-registry/components/administration/workflow/dialogs/edit-bucket-policy/nf-registry-edit-bucket-policy.js');
+var NfRegistryAddPolicyToBucket = require('nifi-registry/components/administration/workflow/dialogs/add-policy-to-bucket/nf-registry-add-policy-to-bucket.js');
 var NfRegistryAddUserToGroups = require('nifi-registry/components/administration/users/dialogs/add-user-to-groups/nf-registry-add-user-to-groups.js');
 var NfRegistryAddUsersToGroup = require('nifi-registry/components/administration/users/dialogs/add-users-to-group/nf-registry-add-users-to-group.js');
 var NfRegistryManageUser = require('nifi-registry/components/administration/users/sidenav/manage-user/nf-registry-manage-user.js');
 var NfRegistryManageGroup = require('nifi-registry/components/administration/users/sidenav/manage-group/nf-registry-manage-group.js');
-var NfRegistryBucketPermissions = require('nifi-registry/components/administration/workflow/buckets/permissions/nf-registry-bucket-permissions.js');
+var NfRegistryManageBucket = require('nifi-registry/components/administration/workflow/sidenav/manage-bucket/nf-registry-manage-bucket.js');
 var NfRegistryWorkflowAdministration = require('nifi-registry/components/administration/workflow/nf-registry-workflow-administration.js');
-var NfRegistryCreateBucket = require('nifi-registry/components/administration/workflow/dialogs/nf-registry-create-bucket.js');
+var NfRegistryCreateBucket = require('nifi-registry/components/administration/workflow/dialogs/create-bucket/nf-registry-create-bucket.js');
 var NfRegistryGridListViewer = require('nifi-registry/components/explorer/grid-list/registry/nf-registry-grid-list-viewer.js');
 var NfRegistryBucketGridListViewer = require('nifi-registry/components/explorer/grid-list/registry/nf-registry-bucket-grid-list-viewer.js');
 var NfRegistryDropletGridListViewer = require('nifi-registry/components/explorer/grid-list/registry/nf-registry-droplet-grid-list-viewer.js');
@@ -70,13 +72,15 @@ NfRegistryModule.annotations = [
             NfRegistryUsersAdministration,
             NfRegistryManageUser,
             NfRegistryManageGroup,
-            NfRegistryBucketPermissions,
+            NfRegistryManageBucket,
             NfRegistryWorkflowAdministration,
             NfRegistryAddUser,
             NfRegistryCreateBucket,
             NfRegistryCreateNewGroup,
             NfRegistryAddUserToGroups,
             NfRegistryAddUsersToGroup,
+            NfRegistryAddPolicyToBucket,
+            NfRegistryEditBucketPolicy,
             NfRegistryGridListViewer,
             NfRegistryBucketGridListViewer,
             NfRegistryDropletGridListViewer,
@@ -90,6 +94,8 @@ NfRegistryModule.annotations = [
             NfRegistryCreateNewGroup,
             NfRegistryAddUserToGroups,
             NfRegistryAddUsersToGroup,
+            NfRegistryAddPolicyToBucket,
+            NfRegistryEditBucketPolicy,
             NfUserLoginComponent
         ],
         providers: [

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/6c48025c/nifi-registry-web-ui/src/main/webapp/nf-registry.routes.js
----------------------------------------------------------------------
diff --git a/nifi-registry-web-ui/src/main/webapp/nf-registry.routes.js b/nifi-registry-web-ui/src/main/webapp/nf-registry.routes.js
index 9413777..3d724d6 100644
--- a/nifi-registry-web-ui/src/main/webapp/nf-registry.routes.js
+++ b/nifi-registry-web-ui/src/main/webapp/nf-registry.routes.js
@@ -24,7 +24,7 @@ var NfRegistryAdministration = require('nifi-registry/components/administration/
 var NfRegistryUsersAdministration = require('nifi-registry/components/administration/users/nf-registry-users-administration.js');
 var NfRegistryManageUser = require('nifi-registry/components/administration/users/sidenav/manage-user/nf-registry-manage-user.js');
 var NfRegistryManageGroup = require('nifi-registry/components/administration/users/sidenav/manage-group/nf-registry-manage-group.js');
-var NfRegistryBucketPermissions = require('nifi-registry/components/administration/workflow/buckets/permissions/nf-registry-bucket-permissions.js');
+var NfRegistryManageBucket = require('nifi-registry/components/administration/workflow/sidenav/manage-bucket/nf-registry-manage-bucket.js');
 var NfRegistryWorkflowAdministration = require('nifi-registry/components/administration/workflow/nf-registry-workflow-administration.js');
 var NfRegistryGridListViewer = require('nifi-registry/components/explorer/grid-list/registry/nf-registry-grid-list-viewer.js');
 var NfRegistryBucketGridListViewer = require('nifi-registry/components/explorer/grid-list/registry/nf-registry-bucket-grid-list-viewer.js');
@@ -79,8 +79,7 @@ var NfRegistryRoutes = new ngRouter.RouterModule.forRoot([{
     pathMatch: 'full'
 }, {
     path: 'nifi-registry',
-    redirectTo: '/nifi-registry/explorer/grid-list',
-    pathMatch: 'full'
+    redirectTo: '/nifi-registry/explorer/grid-list'
 }, {
     path: '',
     redirectTo: '/nifi-registry/explorer/grid-list',
@@ -99,8 +98,8 @@ var NfRegistryRoutes = new ngRouter.RouterModule.forRoot([{
     canActivate: [nfRegistryAuthGuardService.NfRegistryUsersAdministrationAuthGuard],
     outlet: 'sidenav'
 }, {
-    path: 'bucket/permissions/:bucketId',
-    component: NfRegistryBucketPermissions,
+    path: 'manage/bucket/:bucketId',
+    component: NfRegistryManageBucket,
     canActivate: [nfRegistryAuthGuardService.NfRegistryWorkflowsAdministrationAuthGuard],
     outlet: 'sidenav'
 }]);

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/6c48025c/nifi-registry-web-ui/src/main/webapp/nf-registry.spec.js
----------------------------------------------------------------------
diff --git a/nifi-registry-web-ui/src/main/webapp/nf-registry.spec.js b/nifi-registry-web-ui/src/main/webapp/nf-registry.spec.js
index 09632be..bb0adf1 100644
--- a/nifi-registry-web-ui/src/main/webapp/nf-registry.spec.js
+++ b/nifi-registry-web-ui/src/main/webapp/nf-registry.spec.js
@@ -29,7 +29,7 @@ var NfRegistryUsersAdministration = require('nifi-registry/components/administra
 var NfRegistryAddUser = require('nifi-registry/components/administration/users/dialogs/add-user/nf-registry-add-user.js');
 var NfRegistryManageGroup = require('nifi-registry/components/administration/users/sidenav/manage-group/nf-registry-manage-group.js');
 var NfRegistryManageUser = require('nifi-registry/components/administration/users/sidenav/manage-user/nf-registry-manage-user.js');
-var NfRegistryBucketPermissions = require('nifi-registry/components/administration/workflow/buckets/permissions/nf-registry-bucket-permissions.js');
+var NfRegistryManageBucket = require('nifi-registry/components/administration/workflow/sidenav/manage-bucket/nf-registry-manage-bucket.js');
 var NfRegistryWorkflowAdministration = require('nifi-registry/components/administration/workflow/nf-registry-workflow-administration.js');
 var NfRegistryGridListViewer = require('nifi-registry/components/explorer/grid-list/registry/nf-registry-grid-list-viewer.js');
 var NfRegistryBucketGridListViewer = require('nifi-registry/components/explorer/grid-list/registry/nf-registry-bucket-grid-list-viewer.js');
@@ -67,7 +67,7 @@ describe('NfRegistry Component', function () {
                 NfRegistryUsersAdministration,
                 NfRegistryManageUser,
                 NfRegistryManageGroup,
-                NfRegistryBucketPermissions,
+                NfRegistryManageBucket,
                 NfRegistryAddUser,
                 NfRegistryWorkflowAdministration,
                 NfRegistryGridListViewer,

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/6c48025c/nifi-registry-web-ui/src/main/webapp/services/nf-registry.api.js
----------------------------------------------------------------------
diff --git a/nifi-registry-web-ui/src/main/webapp/services/nf-registry.api.js b/nifi-registry-web-ui/src/main/webapp/services/nf-registry.api.js
index 08bec02..3e9d307 100644
--- a/nifi-registry-web-ui/src/main/webapp/services/nf-registry.api.js
+++ b/nifi-registry-web-ui/src/main/webapp/services/nf-registry.api.js
@@ -66,7 +66,7 @@ NfRegistryApi.prototype = {
             .catch(function (error) {
                 self.dialogService.openConfirm({
                     title: 'Error',
-                    message: error.message,
+                    message: error.error,
                     acceptButton: 'Ok',
                     acceptButtonColor: 'fds-warn'
                 });
@@ -92,7 +92,7 @@ NfRegistryApi.prototype = {
             .catch(function (error) {
                 self.dialogService.openConfirm({
                     title: 'Error',
-                    message: error.message,
+                    message: error.error,
                     acceptButton: 'Ok',
                     acceptButtonColor: 'fds-warn'
                 }).afterClosed().subscribe(
@@ -127,7 +127,7 @@ NfRegistryApi.prototype = {
             .catch(function (error) {
                 self.dialogService.openConfirm({
                     title: 'Error',
-                    message: error.message,
+                    message: error.error,
                     acceptButton: 'Ok',
                     acceptButtonColor: 'fds-warn'
                 });
@@ -155,7 +155,7 @@ NfRegistryApi.prototype = {
             .catch(function (error) {
                 self.dialogService.openConfirm({
                     title: 'Error',
-                    message: error.message,
+                    message: error.error,
                     acceptButton: 'Ok',
                     acceptButtonColor: 'fds-warn'
                 });
@@ -178,7 +178,7 @@ NfRegistryApi.prototype = {
             .catch(function (error) {
                 self.dialogService.openConfirm({
                     title: 'Error',
-                    message: error.message,
+                    message: error.error,
                     acceptButton: 'Ok',
                     acceptButtonColor: 'fds-warn'
                 });
@@ -201,7 +201,7 @@ NfRegistryApi.prototype = {
             .catch(function (error) {
                 self.dialogService.openConfirm({
                     title: 'Error',
-                    message: error.message,
+                    message: error.error,
                     acceptButton: 'Ok',
                     acceptButtonColor: 'fds-warn'
                 });
@@ -225,7 +225,7 @@ NfRegistryApi.prototype = {
             .catch(function (error) {
                 self.dialogService.openConfirm({
                     title: 'Error',
-                    message: error.message,
+                    message: error.error,
                     acceptButton: 'Ok',
                     acceptButtonColor: 'fds-warn'
                 }).afterClosed().subscribe(
@@ -256,7 +256,7 @@ NfRegistryApi.prototype = {
             .catch(function (error) {
                 self.dialogService.openConfirm({
                     title: 'Error',
-                    message: error.message,
+                    message: error.error,
                     acceptButton: 'Ok',
                     acceptButtonColor: 'fds-warn'
                 });
@@ -265,6 +265,27 @@ NfRegistryApi.prototype = {
     },
 
     /**
+     * Updates a bucket.
+     *
+     * @param {string} identifier   The identifier of the bucket.
+     * @param {string} name         The name of the bucket.
+     * @returns {*}
+     */
+    updateBucket: function (identifier, name) {
+        var self = this;
+        return this.http.put('/nifi-registry-api/buckets/' + identifier, {
+            'identifier': identifier,
+            'name': name
+        }, headers)
+            .map(function (response) {
+                return response;
+            })
+            .catch(function (error) {
+                return rxjs.Observable.of(error);
+            });
+    },
+
+    /**
      * Get user by id.
      *
      * @param userId
@@ -279,11 +300,11 @@ NfRegistryApi.prototype = {
             .catch(function (error) {
                 self.dialogService.openConfirm({
                     title: 'Error',
-                    message: error.message,
+                    message: error.error,
                     acceptButton: 'Ok',
                     acceptButtonColor: 'fds-warn'
                 });
-                return rxjs.Observable.throw(error.message);
+                return rxjs.Observable.throw(error.error);
             });
     },
 
@@ -331,7 +352,7 @@ NfRegistryApi.prototype = {
             .catch(function (error) {
                 self.dialogService.openConfirm({
                     title: 'Error',
-                    message: error.message,
+                    message: error.error,
                     acceptButton: 'Ok',
                     acceptButtonColor: 'fds-warn'
                 });
@@ -374,7 +395,7 @@ NfRegistryApi.prototype = {
             .catch(function (error) {
                 self.dialogService.openConfirm({
                     title: 'Error',
-                    message: error.message,
+                    message: error.error,
                     acceptButton: 'Ok',
                     acceptButtonColor: 'fds-warn'
                 });
@@ -397,7 +418,7 @@ NfRegistryApi.prototype = {
             .catch(function (error) {
                 self.dialogService.openConfirm({
                     title: 'Error',
-                    message: error.message,
+                    message: error.error,
                     acceptButton: 'Ok',
                     acceptButtonColor: 'fds-warn'
                 });
@@ -419,7 +440,7 @@ NfRegistryApi.prototype = {
             .catch(function (error) {
                 self.dialogService.openConfirm({
                     title: 'Error',
-                    message: error.message,
+                    message: error.error,
                     acceptButton: 'Ok',
                     acceptButtonColor: 'fds-warn'
                 });
@@ -442,7 +463,7 @@ NfRegistryApi.prototype = {
             .catch(function (error) {
                 self.dialogService.openConfirm({
                     title: 'Error',
-                    message: error.message,
+                    message: error.error,
                     acceptButton: 'Ok',
                     acceptButtonColor: 'fds-warn'
                 });
@@ -465,7 +486,7 @@ NfRegistryApi.prototype = {
             .catch(function (error) {
                 self.dialogService.openConfirm({
                     title: 'Error',
-                    message: error.message,
+                    message: error.error,
                     acceptButton: 'Ok',
                     acceptButtonColor: 'fds-warn'
                 });
@@ -476,9 +497,9 @@ NfRegistryApi.prototype = {
     /**
      * Creates a new group.
      *
-     * @param {string} identifier   The identifier of the user.
-     * @param {string} identity     The identity of the user.
-     * @param {array} users         The array of users to be added to the new group.
+     * @param {string}  identifier      The identifier of the user.
+     * @param {string}  identity        The identity of the user.
+     * @param {array}   users           The array of users to be added to the new group.
      * @returns {*}
      */
     createNewGroup: function (identifier, identity, users) {
@@ -494,7 +515,7 @@ NfRegistryApi.prototype = {
             .catch(function (error) {
                 self.dialogService.openConfirm({
                     title: 'Error',
-                    message: error.message,
+                    message: error.error,
                     acceptButton: 'Ok',
                     acceptButtonColor: 'fds-warn'
                 });
@@ -505,9 +526,9 @@ NfRegistryApi.prototype = {
     /**
      * Updates a group.
      *
-     * @param {string} identifier   The identifier of the group.
-     * @param {string} identity     The identity of the group.
-     * @param {array} users         The array of users in the new group.
+     * @param {string}  identifier   The identifier of the group.
+     * @param {string}  identity     The identity of the group.
+     * @param {array}   users         The array of users in the new group.
      * @returns {*}
      */
     updateUserGroup: function (identifier, identity, users) {
@@ -526,10 +547,46 @@ NfRegistryApi.prototype = {
     },
 
     /**
+     * Get metadata for all policies in the registry for which the client is authorized.
+     *
+     * @returns {*}
+     */
+    getPolicies: function () {
+        var self = this;
+        var url = '/nifi-registry-api/policies';
+        return this.http.get(url)
+            .map(function (response) {
+                return response;
+            })
+            .catch(function (error) {
+                return rxjs.Observable.of(error);
+            });
+    },
+
+    /**
+     * Get resource policies by resource identifier.
+     *
+     * @param {string} action       The name of the resource action (e.g. READ/WRITE/DELETE).
+     * @param {string} resource     The name of the resource (e.g. /buckets, /tenants, /policies, /proxy).
+     * @param {string} resourceId   The resource identifier.
+     * @returns {*}
+     */
+    getResourcePoliciesById: function (action, resource, resourceId) {
+        var self = this;
+        return this.http.get('/nifi-registry-api/policies/' + action + resource + '/' + resourceId)
+            .map(function (response) {
+                return response;
+            })
+            .catch(function (error) {
+                return rxjs.Observable.of(error);
+            });
+    },
+
+    /**
      * Get policy action resource.
      *
      * @param {string} action   The name of the resource action (e.g. READ/WRITE/DELETE).
-     * @param {string} resource   The name of the resource action (e.g. READ/WRITE/DELETE).
+     * @param {string} resource     The name of the resource (e.g. /buckets, /tenants, /policies, /proxy).
      * @returns {*}
      */
     getPolicyActionResource: function (action, resource) {
@@ -537,6 +594,9 @@ NfRegistryApi.prototype = {
         return this.http.get('/nifi-registry-api/policies/' + action + resource)
             .map(function (response) {
                 return response;
+            })
+            .catch(function (error) {
+                return rxjs.Observable.of(error);
             });
     },
 
@@ -545,7 +605,7 @@ NfRegistryApi.prototype = {
      *
      * @param {string} identifier   The identifier of the group.
      * @param {string} action       The name of the resource action (e.g. READ/WRITE/DELETE).
-     * @param {string} resource     The name of the resource.
+     * @param {string} resource     The name of the resource (e.g. /buckets, /tenants, /policies, /proxy).
      * @param {string} users        The users with resource privileges.
      * @param {string} userGroups   The user groups with resource privileges.
      * @returns {*}
@@ -565,7 +625,7 @@ NfRegistryApi.prototype = {
             .catch(function (error) {
                 self.dialogService.openConfirm({
                     title: 'Error',
-                    message: error.message,
+                    message: error.error,
                     acceptButton: 'Ok',
                     acceptButtonColor: 'fds-warn'
                 });
@@ -577,7 +637,7 @@ NfRegistryApi.prototype = {
      * Creates a policy action resource.
      *
      * @param {string} action       The name of the resource action (e.g. READ/WRITE/DELETE).
-     * @param {string} resource     The name of the resource.
+     * @param {string} resource     The name of the resource (e.g. /buckets, /tenants, /policies, /proxy).
      * @param {string} users        The users with resource privileges.
      * @param {string} userGroups   The user groups with resource privileges.
      * @returns {*}
@@ -596,7 +656,7 @@ NfRegistryApi.prototype = {
             .catch(function (error) {
                 self.dialogService.openConfirm({
                     title: 'Error',
-                    message: error.message,
+                    message: error.error,
                     acceptButton: 'Ok',
                     acceptButtonColor: 'fds-warn'
                 });
@@ -613,12 +673,29 @@ NfRegistryApi.prototype = {
      */
     postToLogin: function (username, password) {
         var self = this;
-        return this.http.post('/nifi-registry-api/access/token/login', {
-            'username': username,
-            'password': password
-        }, headers)
-            .map(function (response) {
-                return response;
+        var headers = new ngCommonHttp.HttpHeaders({
+            'Content-Type': 'application/x-www-form-urlencoded'
+        });
+        var params = new ngCommonHttp.HttpParams()
+            .set('username', username)
+            .set('password', password)
+            .set('grant_type', 'password');
+
+        var options = {
+            headers: headers,
+            params: params,
+            withCredentials: true,
+            responseType: 'text'
+        };
+        return this.http.post('/nifi-registry-api/access/token/login', null, options)
+            .map(function (jwt) {
+                // get the payload and store the token with the appropriate expiration
+                var token = self.nfStorage.getJwtPayload(jwt);
+                if (token) {
+                    var expiration = parseInt(token['exp'], 10) * MILLIS_PER_SECOND;
+                    self.nfStorage.setItem('jwt', jwt, expiration);
+                }
+                return jwt;
             })
             .catch(function (error) {
                 self.dialogService.openConfirm({
@@ -627,7 +704,7 @@ NfRegistryApi.prototype = {
                     acceptButton: 'Ok',
                     acceptButtonColor: 'fds-warn'
                 });
-                return rxjs.Observable.of(error);
+                return rxjs.Observable.of('');
             });
     },
 

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/6c48025c/nifi-registry-web-ui/src/main/webapp/services/nf-registry.api.spec.js
----------------------------------------------------------------------
diff --git a/nifi-registry-web-ui/src/main/webapp/services/nf-registry.api.spec.js b/nifi-registry-web-ui/src/main/webapp/services/nf-registry.api.spec.js
index 3c9b6d6..76c9820 100644
--- a/nifi-registry-web-ui/src/main/webapp/services/nf-registry.api.spec.js
+++ b/nifi-registry-web-ui/src/main/webapp/services/nf-registry.api.spec.js
@@ -30,7 +30,7 @@ var NfRegistryUsersAdministration = require('nifi-registry/components/administra
 var NfRegistryAddUser = require('nifi-registry/components/administration/users/dialogs/add-user/nf-registry-add-user.js');
 var NfRegistryManageUser = require('nifi-registry/components/administration/users/sidenav/manage-user/nf-registry-manage-user.js');
 var NfRegistryManageGroup = require('nifi-registry/components/administration/users/sidenav/manage-group/nf-registry-manage-group.js');
-var NfRegistryBucketPermissions = require('nifi-registry/components/administration/workflow/buckets/permissions/nf-registry-bucket-permissions.js');
+var NfRegistryManageBucket = require('nifi-registry/components/administration/workflow/sidenav/manage-bucket/nf-registry-manage-bucket.js');
 var NfRegistryWorkflowAdministration = require('nifi-registry/components/administration/workflow/nf-registry-workflow-administration.js');
 var NfRegistryGridListViewer = require('nifi-registry/components/explorer/grid-list/registry/nf-registry-grid-list-viewer.js');
 var NfRegistryBucketGridListViewer = require('nifi-registry/components/explorer/grid-list/registry/nf-registry-bucket-grid-list-viewer.js');
@@ -44,6 +44,7 @@ var NfRegistryAuthService = require('nifi-registry/services/nf-registry.auth.ser
 var NfStorage = require('nifi-registry/services/nf-storage.service.js');
 var NfLoginComponent = require('nifi-registry/components/login/nf-registry-login.js');
 var NfUserLoginComponent = require('nifi-registry/components/login/dialogs/nf-registry-user-login.js');
+var nfRegistryAuthGuardService = require('nifi-registry/services/nf-registry.auth-guard.service.js');
 
 xdescribe('NfRegistry API w/ Angular testing utils', function () {
     var nfRegistryApi;
@@ -65,7 +66,7 @@ xdescribe('NfRegistry API w/ Angular testing utils', function () {
                 NfRegistryUsersAdministration,
                 NfRegistryManageUser,
                 NfRegistryManageGroup,
-                NfRegistryBucketPermissions,
+                NfRegistryManageBucket,
                 NfRegistryAddUser,
                 NfRegistryWorkflowAdministration,
                 NfRegistryGridListViewer,
@@ -77,6 +78,10 @@ xdescribe('NfRegistry API w/ Angular testing utils', function () {
             ],
             providers: [
                 NfRegistryService,
+                nfRegistryAuthGuardService.NfRegistryUsersAdministrationAuthGuard,
+                nfRegistryAuthGuardService.NfRegistryWorkflowsAdministrationAuthGuard,
+                nfRegistryAuthGuardService.NfRegistryLoginAuthGuard,
+                nfRegistryAuthGuardService.NfRegistryResourcesAuthGuard,
                 NfRegistryAuthService,
                 NfRegistryApi,
                 NfStorage,
@@ -236,7 +241,7 @@ xdescribe('NfRegistry API w/ Angular testing utils', function () {
         expect(req.request.method).toEqual('GET');
 
         // Next, fulfill the request by transmitting a response.
-        req.flush(null, {status: 401, statusText: 'GET droplet mock error'});
+        req.flush('Http failure response for /nifi-registry-api/flow/test/versions: 401 GET droplet mock error', {status: 401, statusText: 'GET droplet mock error'});
 
         // Finally, assert that there are no outstanding requests.
         httpMock.verify();
@@ -300,7 +305,7 @@ xdescribe('NfRegistry API w/ Angular testing utils', function () {
         expect(req.request.method).toEqual('GET');
 
         // Next, fulfill the request by transmitting a response.
-        req.flush(null, {status: 401, statusText: 'GET droplet mock error'});
+        req.flush('Http failure response for /nifi-registry-api/buckets/2f7f9e54-dc09-4ceb-aa58-9fe581319cdc/flows/2e04b4fb-9513-47bb-aa74-1ae34616bfdc: 401 GET droplet mock error', {status: 401, statusText: 'GET droplet mock error'});
 
         // Finally, assert that there are no outstanding requests.
         httpMock.verify();
@@ -376,7 +381,7 @@ xdescribe('NfRegistry API w/ Angular testing utils', function () {
         expect(req.request.method).toEqual('GET');
 
         // Next, fulfill the request by transmitting a response.
-        req.flush(null, {status: 401, statusText: 'GET droplet mock error'});
+        req.flush('Http failure response for /nifi-registry-api/items: 401 GET droplet mock error', {status: 401, statusText: 'GET droplet mock error'});
 
         // Finally, assert that there are no outstanding requests.
         httpMock.verify();
@@ -435,7 +440,7 @@ xdescribe('NfRegistry API w/ Angular testing utils', function () {
         expect(req.request.method).toEqual('GET');
 
         // Next, fulfill the request by transmitting a response.
-        req.flush(null, {status: 401, statusText: 'GET droplet mock error'});
+        req.flush('Http failure response for /nifi-registry-api/items/2f7f9e54-dc09-4ceb-aa58-9fe581319cdc: 401 GET droplet mock error', {status: 401, statusText: 'GET droplet mock error'});
 
         // Finally, assert that there are no outstanding requests.
         httpMock.verify();
@@ -477,7 +482,7 @@ xdescribe('NfRegistry API w/ Angular testing utils', function () {
         expect(req.request.method).toEqual('DELETE');
 
         // Next, fulfill the request by transmitting a response.
-        req.flush(null, {status: 401, statusText: 'DELETE droplet mock error'});
+        req.flush('Http failure response for /nifi-registry-api/flows/1234: 401 DELETE droplet mock error', {status: 401, statusText: 'DELETE droplet mock error'});
 
         // Finally, assert that there are no outstanding requests.
         httpMock.verify();
@@ -521,7 +526,7 @@ xdescribe('NfRegistry API w/ Angular testing utils', function () {
         expect(req.request.method).toEqual('POST');
 
         // Next, fulfill the request by transmitting a response.
-        req.flush(null, {status: 401, statusText: 'POST bucket mock error'});
+        req.flush('Http failure response for /nifi-registry-api/buckets: 401 POST bucket mock error', {status: 401, statusText: 'POST bucket mock error'});
 
         // Finally, assert that there are no outstanding requests.
         httpMock.verify();
@@ -561,7 +566,7 @@ xdescribe('NfRegistry API w/ Angular testing utils', function () {
         expect(req.request.method).toEqual('DELETE');
 
         // Next, fulfill the request by transmitting a response.
-        req.flush(null, {status: 401, statusText: 'DELETE bucket mock error'});
+        req.flush('Http failure response for /nifi-registry-api/buckets/1234: 401 DELETE bucket mock error', {status: 401, statusText: 'DELETE bucket mock error'});
 
         // Finally, assert that there are no outstanding requests.
         httpMock.verify();
@@ -621,7 +626,7 @@ xdescribe('NfRegistry API w/ Angular testing utils', function () {
         expect(req.request.method).toEqual('GET');
 
         // Next, fulfill the request by transmitting a response.
-        req.flush(null, {status: 401, statusText: 'GET bucket mock error'});
+        req.flush('Http failure response for /nifi-registry-api/buckets/2f7f9e54-dc09-4ceb-aa58-9fe581319cdc: 401 GET bucket mock error', {status: 401, statusText: 'GET bucket mock error'});
 
         // Finally, assert that there are no outstanding requests.
         httpMock.verify();
@@ -667,7 +672,7 @@ xdescribe('NfRegistry API w/ Angular testing utils', function () {
         expect(req.request.method).toEqual('GET');
 
         // Next, fulfill the request by transmitting a response.
-        req.flush(null, {status: 401, statusText: 'GET metadata mock error'});
+        req.flush('Http failure response for /nifi-registry-api/buckets: 401 GET metadata mock error', {status: 401, statusText: 'GET metadata mock error'});
 
         // Finally, assert that there are no outstanding requests.
         httpMock.verify();
@@ -712,7 +717,7 @@ xdescribe('NfRegistry API w/ Angular testing utils', function () {
         expect(req.request.method).toEqual('POST');
 
         // Next, fulfill the request by transmitting a response.
-        req.flush(null, {status: 401, statusText: 'POST add user mock error'});
+        req.flush('Http failure response for /nifi-registry-api/tenants/users: 401 POST add user mock error', {status: 401, statusText: 'POST add user mock error'});
 
         // Finally, assert that there are no outstanding requests.
         httpMock.verify();
@@ -758,7 +763,7 @@ xdescribe('NfRegistry API w/ Angular testing utils', function () {
         expect(req.request.method).toEqual('GET');
 
         // Next, fulfill the request by transmitting a response.
-        req.flush(null, {status: 401, statusText: 'GET users mock error'});
+        req.flush('Http failure response for /nifi-registry-api/tenants/users: 401 GET users mock error', {status: 401, statusText: 'GET users mock error'});
 
         // Finally, assert that there are no outstanding requests.
         httpMock.verify();
@@ -804,7 +809,7 @@ xdescribe('NfRegistry API w/ Angular testing utils', function () {
         expect(req.request.method).toEqual('DELETE');
 
         // Next, fulfill the request by transmitting a response.
-        req.flush(null, {status: 401, statusText: 'DELETE users mock error'});
+        req.flush('Http failure response for /nifi-registry-api/tenants/users/123: 401 DELETE users mock error', {status: 401, statusText: 'DELETE users mock error'});
 
         // Finally, assert that there are no outstanding requests.
         httpMock.verify();
@@ -850,7 +855,7 @@ xdescribe('NfRegistry API w/ Angular testing utils', function () {
         expect(req.request.method).toEqual('GET');
 
         // Next, fulfill the request by transmitting a response.
-        req.flush(null, {status: 401, statusText: 'GET user groups mock error'});
+        req.flush('Http failure response for /nifi-registry-api/tenants/user-groups: 401 GET user groups mock error', {status: 401, statusText: 'GET user groups mock error'});
 
         // Finally, assert that there are no outstanding requests.
         httpMock.verify();
@@ -896,7 +901,7 @@ xdescribe('NfRegistry API w/ Angular testing utils', function () {
         expect(req.request.method).toEqual('GET');
 
         // Next, fulfill the request by transmitting a response.
-        req.flush(null, {status: 401, statusText: 'GET user groups mock error'});
+        req.flush('Http failure response for /nifi-registry-api/tenants/user-groups/123: 401 GET user groups mock error', {status: 401, statusText: 'GET user groups mock error'});
 
         // Finally, assert that there are no outstanding requests.
         httpMock.verify();
@@ -942,7 +947,7 @@ xdescribe('NfRegistry API w/ Angular testing utils', function () {
         expect(req.request.method).toEqual('DELETE');
 
         // Next, fulfill the request by transmitting a response.
-        req.flush(null, {status: 401, statusText: 'DELETE user groups mock error'});
+        req.flush('Http failure response for /nifi-registry-api/tenants/user-groups/123: 401 DELETE user groups mock error', {status: 401, statusText: 'DELETE user groups mock error'});
 
         // Finally, assert that there are no outstanding requests.
         httpMock.verify();
@@ -997,7 +1002,7 @@ xdescribe('NfRegistry API w/ Angular testing utils', function () {
         expect(req.request.method).toEqual('POST');
 
         // Next, fulfill the request by transmitting a response.
-        req.flush(null, {status: 401, statusText: 'POST user groups mock error'});
+        req.flush('Http failure response for /nifi-registry-api/tenants/user-groups: 401 POST user groups mock error', {status: 401, statusText: 'POST user groups mock error'});
 
         // Finally, assert that there are no outstanding requests.
         httpMock.verify();

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/6c48025c/nifi-registry-web-ui/src/main/webapp/services/nf-registry.auth-guard.service.js
----------------------------------------------------------------------
diff --git a/nifi-registry-web-ui/src/main/webapp/services/nf-registry.auth-guard.service.js b/nifi-registry-web-ui/src/main/webapp/services/nf-registry.auth-guard.service.js
index 71580a2..a2f34f3 100644
--- a/nifi-registry-web-ui/src/main/webapp/services/nf-registry.auth-guard.service.js
+++ b/nifi-registry-web-ui/src/main/webapp/services/nf-registry.auth-guard.service.js
@@ -51,7 +51,6 @@ NfRegistryUsersAdministrationAuthGuard.prototype = {
         this.nfRegistryService.api.ticketExchange().subscribe(function (jwt) {
             self.nfRegistryService.api.loadCurrentUser().subscribe(function (currentUser) {
                 self.nfRegistryService.currentUser = currentUser;
-                // if the user is logged, we want to determine if they were logged in using a certificate
                 if (currentUser.anonymous === false) {
                     // render the logout button if there is a token locally
                     if (self.nfRegistryService.nfStorage.getItem('jwt') !== null) {
@@ -113,7 +112,6 @@ NfRegistryWorkflowsAdministrationAuthGuard.prototype = {
         this.nfRegistryService.api.ticketExchange().subscribe(function (jwt) {
             self.nfRegistryService.api.loadCurrentUser().subscribe(function (currentUser) {
                 self.nfRegistryService.currentUser = currentUser;
-                // if the user is logged, we want to determine if they were logged in using a certificate
                 if (currentUser.anonymous === false) {
                     // render the logout button if there is a token locally
                     if (self.nfRegistryService.nfStorage.getItem('jwt') !== null) {
@@ -175,14 +173,15 @@ NfRegistryLoginAuthGuard.prototype = {
         this.nfRegistryService.api.ticketExchange().subscribe(function (jwt) {
             self.nfRegistryService.api.loadCurrentUser().subscribe(function (currentUser) {
                 self.nfRegistryService.currentUser = currentUser;
-                // if the user is logged, we want to determine if they were logged in using a certificate
                 if (currentUser.anonymous === false) {
                     // render the logout button if there is a token locally
                     if (self.nfRegistryService.nfStorage.getItem('jwt') !== null) {
                         self.nfRegistryService.currentUser.canLogout = true;
                     }
+                    self.nfRegistryService.currentUser.canActivateResourcesAuthGuard = true;
                     self.nfRegistryService.router.navigateByUrl(self.nfRegistryService.redirectUrl);
                 } else {
+                    self.nfRegistryService.currentUser.anonymous = true;
                     self.nfRegistryService.router.navigateByUrl('/nifi-registry/login');
                 }
             });
@@ -221,7 +220,7 @@ NfRegistryResourcesAuthGuard.prototype = {
 
     checkLogin: function (url) {
         var self = this;
-        if (this.nfRegistryService.currentUser.resourcePermissions.buckets.canRead) { return true; }
+        if (this.nfRegistryService.currentUser.canActivateResourcesAuthGuard === true) { return true; }
 
         // Store the attempted URL for redirecting
         this.nfRegistryService.redirectUrl = url;
@@ -230,14 +229,22 @@ NfRegistryResourcesAuthGuard.prototype = {
         this.nfRegistryService.api.ticketExchange().subscribe(function (jwt) {
             self.nfRegistryService.api.loadCurrentUser().subscribe(function (currentUser) {
                 self.nfRegistryService.currentUser = currentUser;
-                // if the user is logged, we want to determine if they were logged in using a certificate
-                if (currentUser.anonymous === false) {
+                if (!currentUser || currentUser.anonymous === false) {
+                    if(self.nfRegistryService.nfStorage.hasItem('jwt')){
+                        self.nfRegistryService.currentUser.canLogout = true;
+                        self.nfRegistryService.currentUser.canActivateResourcesAuthGuard = true;
+                        self.nfRegistryService.router.navigateByUrl(url);
+                    } else {
+                        self.nfRegistryService.router.navigateByUrl('/nifi-registry/login');
+                    }
+                } else if (currentUser.anonymous === true) {
                     // render the logout button if there is a token locally
                     if (self.nfRegistryService.nfStorage.getItem('jwt') !== null) {
                         self.nfRegistryService.currentUser.canLogout = true;
                     }
+                    self.nfRegistryService.currentUser.canActivateResourcesAuthGuard = true;
+                    self.nfRegistryService.router.navigateByUrl(url);
                 }
-                self.nfRegistryService.router.navigateByUrl(url);
             });
         });
 

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/6c48025c/nifi-registry-web-ui/src/main/webapp/services/nf-registry.service.js
----------------------------------------------------------------------
diff --git a/nifi-registry-web-ui/src/main/webapp/services/nf-registry.service.js b/nifi-registry-web-ui/src/main/webapp/services/nf-registry.service.js
index 9964ffd..3de0ffb 100644
--- a/nifi-registry-web-ui/src/main/webapp/services/nf-registry.service.js
+++ b/nifi-registry-web-ui/src/main/webapp/services/nf-registry.service.js
@@ -36,8 +36,11 @@ var rxjs = require('rxjs/Observable');
  */
 function NfRegistryService(nfRegistryApi, nfStorage, tdDataTableService, router, fdsDialogService, fdsSnackBarService) {
     this.registry = {
-        name: "Nifi Registry"
+        name: "NiFi Registry"
     };
+    this.documentation = {
+        link: 'nifi-registry-docs/documentation'
+    }
     this.redirectUrl = '/nifi-registry/explorer/grid-list';
 
     // Services
@@ -67,20 +70,20 @@ function NfRegistryService(nfRegistryApi, nfStorage, tdDataTableService, router,
             width: 100
         }
     ];
-    this.userPoliciesColumns = [
+    this.bucketPoliciesColumns = [
         {
             name: 'identity',
-            label: 'Bucket Name',
+            label: 'Display Name',
             sortable: true,
-            tooltip: 'Bucket name.',
-            width: 100
+            tooltip: 'User/Group name.',
+            width: 40
         },
         {
-            name: 'identity',
-            label: 'Bucket Name',
-            sortable: true,
-            tooltip: 'Bucket name.',
-            width: 100
+            name: 'permissions',
+            label: 'Permissions',
+            sortable: false,
+            tooltip: 'User/Group permissions for this bucket.',
+            width: 40
         }
     ];
     this.dropletColumns = [
@@ -106,16 +109,35 @@ function NfRegistryService(nfRegistryApi, nfStorage, tdDataTableService, router,
     ];
 
     // data table available row action definitions
+    this.disableMultiBucketDeleteAction = false;
     this.bucketActions = [
         {
-            'name': 'permissions',
-            'icon': 'fa fa-pencil',
-            'tooltip': 'Manage Bucket Policies',
-            'type': 'sidenav'
+            name: 'manage',
+            icon: 'fa fa-pencil',
+            tooltip: 'Manage Bucket',
+            type: 'sidenav',
+            disabled: function(row) {
+                return false;
+            }
+        }, {
+            name: 'Delete',
+            icon: 'fa fa-trash',
+            tooltip: 'Delete Bucket',
+            disabled: function(row) {
+                return (!row.permissions.canDelete);
+            }
+        }
+    ];
+    this.bucketPoliciesActions = [
+        {
+            name: 'manage',
+            icon: 'fa fa-pencil',
+            tooltip: 'Manage Policy',
+            type: 'dialog'
         }, {
-            'name': 'Delete',
-            'icon': 'fa fa-trash',
-            'tooltip': 'Delete Bucket'
+            name: 'Delete',
+            icon: 'fa fa-trash',
+            tooltip: 'Delete Policy'
         }
     ];
     this.dropletActions = [
@@ -125,17 +147,24 @@ function NfRegistryService(nfRegistryApi, nfStorage, tdDataTableService, router,
             tooltip: 'Delete'
         }
     ];
+    this.disableMultiDeleteAction = false;
     this.usersActions = [
         {
             name: 'manage',
             icon: 'fa fa-pencil',
             tooltip: 'Manage User Policies',
             type: 'sidenav',
-            tooltip: 'Manage User'
+            tooltip: 'Manage User',
+            disabled: function(row) {
+                return false;
+            }
         }, {
             name: 'delete',
             icon: 'fa fa-trash',
-            tooltip: 'Delete User'
+            tooltip: 'Delete User',
+            disabled: function(row) {
+                return (!row.configurable);
+            }
         }
     ];
     this.userGroupsActions = [
@@ -143,11 +172,17 @@ function NfRegistryService(nfRegistryApi, nfStorage, tdDataTableService, router,
             name: 'manage',
             icon: 'fa fa-pencil',
             tooltip: 'Manage User Group Policies',
-            type: 'sidenav'
+            type: 'sidenav',
+            disabled: function(row) {
+                return false;
+            }
         }, {
             name: 'delete',
             icon: 'fa fa-trash',
-            tooltip: 'Delete User Group'
+            tooltip: 'Delete User Group',
+            disabled: function(row) {
+                return (!row.configurable);
+            }
         }
     ];
 
@@ -327,7 +362,7 @@ NfRegistryService.prototype = {
             var label = '';
             switch (sortByColumn.label) {
                 case 'Updated':
-                    label = (sortByColumn.sortOrder === 'ASC') ? 'Newest (update)' : 'Oldest (update)';
+                    label = (sortByColumn.sortOrder === 'ASC') ? 'Oldest (update)' : 'Newest (update)';
                     break;
                 case 'Name':
                     label = (sortByColumn.sortOrder === 'ASC') ? 'Name (a - z)' : 'Name (z - a)';
@@ -347,7 +382,7 @@ NfRegistryService.prototype = {
         var label = '';
         switch (col.label) {
             case 'Updated':
-                label = (col.sortOrder !== 'ASC') ? 'Newest (update)' : 'Oldest (update)';
+                label = (col.sortOrder !== 'ASC') ? 'Oldest (update)' : 'Newest (update)';
                 break;
             case 'Name':
                 label = (col.sortOrder !== 'ASC') ? 'Name (a - z)' : 'Name (z - a)';
@@ -465,7 +500,7 @@ NfRegistryService.prototype = {
         }
 
         for (var i = 0; i < this.dropletsSearchTerms.length; i++) {
-            newData = this.filterData(newData, this.dropletsSearchTerms[i], true, sortBy);
+            newData = this.dataTableService.filterData(newData, this.dropletsSearchTerms[i], true);
         }
 
         newData = this.dataTableService.sortData(newData, sortBy, sortOrder);
@@ -525,8 +560,8 @@ NfRegistryService.prototype = {
                         }
                     });
                 break;
-            case 'permissions':
-                this.router.navigateByUrl('/nifi-registry/administration/workflow(' + action.type + ':bucket/' + action.name + '/' + bucket.identifier + ')');
+            case 'manage':
+                this.router.navigateByUrl('/nifi-registry/administration/workflow(' + action.type + ':' + action.name + '/bucket/' + bucket.identifier + ')');
                 break;
             default:
                 break;
@@ -566,7 +601,7 @@ NfRegistryService.prototype = {
         var newData = this.buckets;
 
         for (var i = 0; i < this.bucketsSearchTerms.length; i++) {
-            newData = this.filterData(newData, this.bucketsSearchTerms[i], true, sortBy);
+            newData = this.dataTableService.filterData(newData, this.bucketsSearchTerms[i], true);
         }
 
         newData = this.dataTableService.sortData(newData, sortBy, sortOrder);
@@ -625,15 +660,20 @@ NfRegistryService.prototype = {
     allFilteredBucketsSelected: function () {
         var selected = 0;
         var allSelected = true;
-        this.filteredBuckets.forEach(function (c) {
-            if (c.checked) {
+        var disableMultiBucketDeleteAction = false;
+        this.filteredBuckets.forEach(function (bucket) {
+            if (bucket.checked) {
                 selected++;
             }
-            if (c.checked === undefined || c.checked === false) {
+            if (bucket.checked === undefined || bucket.checked === false) {
                 allSelected = false;
             }
+            if (bucket.permissions.canDelete === false) {
+                disableMultiBucketDeleteAction = true;
+            }
         });
 
+        this.disableMultiBucketDeleteAction = disableMultiBucketDeleteAction;
         this.isMultiBucketActionsDisabled = (selected > 0) ? false : true;
         return allSelected;
     },
@@ -852,14 +892,14 @@ NfRegistryService.prototype = {
         var newUserGroupsData = this.groups;
 
         for (var i = 0; i < this.usersSearchTerms.length; i++) {
-            newUsersData = this.filterData(newUsersData, this.usersSearchTerms[i], true);
+            newUsersData = this.dataTableService.filterData(newUsersData, this.usersSearchTerms[i], true);
         }
 
         newUsersData = this.dataTableService.sortData(newUsersData, sortBy, sortOrder);
         this.filteredUsers = newUsersData;
 
         for (var i = 0; i < this.usersSearchTerms.length; i++) {
-            newUserGroupsData = this.filterData(newUserGroupsData, this.usersSearchTerms[i], true);
+            newUserGroupsData = this.dataTableService.filterData(newUserGroupsData, this.usersSearchTerms[i], true);
         }
 
         newUserGroupsData = this.dataTableService.sortData(newUserGroupsData, sortBy, sortOrder);
@@ -874,17 +914,25 @@ NfRegistryService.prototype = {
      */
     determineAllUsersAndGroupsSelectedState: function () {
         var allSelected = true;
-        this.filteredUserGroups.forEach(function (c) {
-            if (c.checked === undefined || c.checked === false) {
+        var disableMultiDeleteAction = false;
+        this.filteredUserGroups.forEach(function (group) {
+            if (group.checked === undefined || group.checked === false) {
                 allSelected = false;
             }
+            if (group.checked && group.configurable === false) {
+                disableMultiDeleteAction = true;
+            }
         });
 
-        this.filteredUsers.forEach(function (c) {
-            if (c.checked === undefined || c.checked === false) {
+        this.filteredUsers.forEach(function (user) {
+            if (user.checked === undefined || user.checked === false) {
                 allSelected = false;
             }
+            if (user.checked && user.configurable === false) {
+                disableMultiDeleteAction = true;
+            }
         });
+        this.disableMultiDeleteAction = disableMultiDeleteAction;
         this.allUsersAndGroupsSelected = allSelected;
     },
 
@@ -933,7 +981,7 @@ NfRegistryService.prototype = {
         this.filteredUserGroups.forEach(function (c) {
             c.checked = true;
         });
-        this.allUsersAndGroupsSelected = true;
+        this.determineAllUsersAndGroupsSelectedState();
     },
 
     /**
@@ -947,7 +995,7 @@ NfRegistryService.prototype = {
         this.filteredUserGroups.forEach(function (c) {
             c.checked = false;
         });
-        this.allUsersAndGroupsSelected = false;
+        this.determineAllUsersAndGroupsSelectedState();
     },
 
     /**
@@ -1006,6 +1054,8 @@ NfRegistryService.prototype = {
             case 'manage':
                 this.router.navigateByUrl('/nifi-registry/administration/users(' + action.type + ':' + action.name + '/user/' + user.identifier + ')');
                 break;
+            default:
+                break;
         }
     },
 
@@ -1051,6 +1101,8 @@ NfRegistryService.prototype = {
             case 'manage':
                 this.router.navigateByUrl('/nifi-registry/administration/users(' + action.type + ':' + action.name + '/group/' + group.identifier + ')');
                 break;
+            default:
+                break;
         }
     },
 
@@ -1112,6 +1164,7 @@ NfRegistryService.prototype = {
             });
     },
 
+
     /**
      * Utility method that performs the custom search capability for data tables.
      *
@@ -1120,7 +1173,7 @@ NfRegistryService.prototype = {
      * @param ignoreCase    Ignore case.
      * @returns {*}
      */
-    filterData: function (data, searchTerm, ignoreCase) {
+    experimental_filterData: function (data, searchTerm, ignoreCase) {
         var field = '';
         if (searchTerm.indexOf(":") > -1) {
             field = searchTerm.split(':')[0].trim();

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/6c48025c/nifi-registry-web-ui/src/main/webapp/services/nf-registry.service.spec.js
----------------------------------------------------------------------
diff --git a/nifi-registry-web-ui/src/main/webapp/services/nf-registry.service.spec.js b/nifi-registry-web-ui/src/main/webapp/services/nf-registry.service.spec.js
index e3d3164..bfd1446 100644
--- a/nifi-registry-web-ui/src/main/webapp/services/nf-registry.service.spec.js
+++ b/nifi-registry-web-ui/src/main/webapp/services/nf-registry.service.spec.js
@@ -30,7 +30,7 @@ var NfRegistryUsersAdministration = require('nifi-registry/components/administra
 var NfRegistryAddUser = require('nifi-registry/components/administration/users/dialogs/add-user/nf-registry-add-user.js');
 var NfRegistryManageUser = require('nifi-registry/components/administration/users/sidenav/manage-user/nf-registry-manage-user.js');
 var NfRegistryManageGroup = require('nifi-registry/components/administration/users/sidenav/manage-group/nf-registry-manage-group.js');
-var NfRegistryBucketPermissions = require('nifi-registry/components/administration/workflow/buckets/permissions/nf-registry-bucket-permissions.js');
+var NfRegistryManageBucket = require('nifi-registry/components/administration/workflow/sidenav/manage-bucket/nf-registry-manage-bucket.js');
 var NfRegistryWorkflowAdministration = require('nifi-registry/components/administration/workflow/nf-registry-workflow-administration.js');
 var NfRegistryGridListViewer = require('nifi-registry/components/explorer/grid-list/registry/nf-registry-grid-list-viewer.js');
 var NfRegistryBucketGridListViewer = require('nifi-registry/components/explorer/grid-list/registry/nf-registry-bucket-grid-list-viewer.js');
@@ -85,7 +85,7 @@ describe('NfRegistry Service isolated unit tests', function () {
         expect(label).toBe('Name (a - z)');
     });
 
-    it('should get the `Oldest (update)` sort by label', function () {
+    it('should get the `Newest (update)` sort by label', function () {
         //Setup the nfRegistryService state for this test
         nfRegistryService.dropletColumns[0].active = false;
         nfRegistryService.dropletColumns[1].active = true;
@@ -94,10 +94,10 @@ describe('NfRegistry Service isolated unit tests', function () {
         var label = nfRegistryService.getSortByLabel();
 
         //assertions
-        expect(label).toBe('Oldest (update)');
+        expect(label).toBe('Newest (update)');
     });
 
-    it('should get the `Newest (update)` sort by label', function () {
+    it('should get the `Oldest (update)` sort by label', function () {
         //Setup the nfRegistryService state for this test
         nfRegistryService.dropletColumns[0].active = false;
         nfRegistryService.dropletColumns[1].active = true;
@@ -107,7 +107,7 @@ describe('NfRegistry Service isolated unit tests', function () {
         var label = nfRegistryService.getSortByLabel();
 
         //assertions
-        expect(label).toBe('Newest (update)');
+        expect(label).toBe('Oldest (update)');
     });
 
     it('should generate the sort menu\'s `Name (a - z)` label', function () {
@@ -131,15 +131,15 @@ describe('NfRegistry Service isolated unit tests', function () {
         expect(label).toBe('Name (z - a)');
     });
 
-    it('should generate the sort menu\'s `Newest (update)` label', function () {
+    it('should generate the sort menu\'s `Oldest (update)` label', function () {
         // The function to test
         var label = nfRegistryService.generateSortMenuLabels({name: 'updated', label: 'Updated', sortable: true});
 
         //assertions
-        expect(label).toBe('Newest (update)');
+        expect(label).toBe('Oldest (update)');
     });
 
-    it('should generate the sort menu\'s `Oldest (update)` label', function () {
+    it('should generate the sort menu\'s `Newest (update)` label', function () {
         // The function to test
         var label = nfRegistryService.generateSortMenuLabels({
             name: 'updated',
@@ -149,7 +149,7 @@ describe('NfRegistry Service isolated unit tests', function () {
         });
 
         //assertions
-        expect(label).toBe('Oldest (update)');
+        expect(label).toBe('Newest (update)');
     });
 
     it('should sort `droplets` by `column`', function () {
@@ -275,10 +275,12 @@ describe('NfRegistry Service isolated unit tests', function () {
         //Setup the nfRegistryService state for this test
         nfRegistryService.filteredBuckets = [{
             'identifier': '2e04b4fb-9513-47bb-aa74-1ae34616bfdc',
-            'name': 'Bucket #1'
+            'name': 'Bucket #1',
+            'permissions': []
         }, {
             'identifier': '5c04b4fb-9513-47bb-aa74-1ae34616bfdc',
-            'name': 'Bucket #2'
+            'name': 'Bucket #2',
+            'permissions': []
         }];
 
         // The function to test
@@ -294,11 +296,13 @@ describe('NfRegistry Service isolated unit tests', function () {
         nfRegistryService.filteredBuckets = [{
             'identifier': '2e04b4fb-9513-47bb-aa74-1ae34616bfdc',
             'name': 'Bucket #1',
-            'checked': true
+            'checked': true,
+            'permissions': []
         }, {
             'identifier': '5c04b4fb-9513-47bb-aa74-1ae34616bfdc',
             'name': 'Bucket #2',
-            'checked': true
+            'checked': true,
+            'permissions': []
         }];
 
         // The function to test
@@ -693,7 +697,7 @@ describe('NfRegistry Service w/ Angular testing utils', function () {
                 NfRegistryUsersAdministration,
                 NfRegistryManageUser,
                 NfRegistryManageGroup,
-                NfRegistryBucketPermissions,
+                NfRegistryManageBucket,
                 NfRegistryAddUser,
                 NfRegistryWorkflowAdministration,
                 NfRegistryGridListViewer,
@@ -915,7 +919,7 @@ describe('NfRegistry Service w/ Angular testing utils', function () {
         expect(nfRegistryService.buckets[0].identifier).toBe(1);
     });
 
-    it('should execute a `permissions` action on a bucket.', function () {
+    it('should execute a `manage` action on a bucket.', function () {
         // from the root injector
         var router = ngCoreTesting.TestBed.get(ngRouter.Router);
 
@@ -927,11 +931,11 @@ describe('NfRegistry Service w/ Angular testing utils', function () {
         var bucket = {identifier: '999'};
 
         // The function to test
-        nfRegistryService.executeBucketAction({name: 'permissions', type: 'sidenav'}, bucket);
+        nfRegistryService.executeBucketAction({name: 'manage', type: 'sidenav'}, bucket);
 
         //assertions
         var navigateByUrlCall = router.navigateByUrl.calls.first();
-        expect(navigateByUrlCall.args[0]).toBe('/nifi-registry/administration/workflow(sidenav:bucket/permissions/999)');
+        expect(navigateByUrlCall.args[0]).toBe('/nifi-registry/administration/workflow(sidenav:manage/bucket/999)');
     });
 
     it('should execute a `delete` action on a user.', function () {

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/6c48025c/nifi-registry-web-ui/src/main/webapp/systemjs.builder.config.js
----------------------------------------------------------------------
diff --git a/nifi-registry-web-ui/src/main/webapp/systemjs.builder.config.js b/nifi-registry-web-ui/src/main/webapp/systemjs.builder.config.js
index a66d70d..77d27f9 100644
--- a/nifi-registry-web-ui/src/main/webapp/systemjs.builder.config.js
+++ b/nifi-registry-web-ui/src/main/webapp/systemjs.builder.config.js
@@ -114,8 +114,10 @@
             'nifi-registry/components/administration/users/dialogs/add-user-to-groups/nf-registry-add-user-to-groups.js': 'components/administration/users/dialogs/add-user-to-groups/nf-registry-add-user-to-groups.js',
             'nifi-registry/components/administration/users/sidenav/manage-user/nf-registry-manage-user.js': 'components/administration/users/sidenav/manage-user/nf-registry-manage-user.js',
             'nifi-registry/components/administration/users/sidenav/manage-group/nf-registry-manage-group.js': 'components/administration/users/sidenav/manage-group/nf-registry-manage-group.js',
-            'nifi-registry/components/administration/workflow/dialogs/nf-registry-create-bucket.js': 'components/administration/workflow/dialogs/nf-registry-create-bucket.js',
-            'nifi-registry/components/administration/workflow/buckets/permissions/nf-registry-bucket-permissions.js': 'components/administration/workflow/buckets/permissions/nf-registry-bucket-permissions.js',
+            'nifi-registry/components/administration/workflow/dialogs/create-bucket/nf-registry-create-bucket.js': 'components/administration/workflow/dialogs/create-bucket/nf-registry-create-bucket.js',
+            'nifi-registry/components/administration/workflow/dialogs/edit-bucket-policy/nf-registry-edit-bucket-policy.js': 'components/administration/workflow/dialogs/edit-bucket-policy/nf-registry-edit-bucket-policy.js',
+            'nifi-registry/components/administration/workflow/dialogs/add-policy-to-bucket/nf-registry-add-policy-to-bucket.js': 'components/administration/workflow/dialogs/add-policy-to-bucket/nf-registry-add-policy-to-bucket.js',
+            'nifi-registry/components/administration/workflow/sidenav/manage-bucket/nf-registry-manage-bucket.js': 'components/administration/workflow/sidenav/manage-bucket/nf-registry-manage-bucket.js',
             'nifi-registry/components/administration/workflow/nf-registry-workflow-administration.js': 'components/administration/workflow/nf-registry-workflow-administration.js',
             'nifi-registry/components/explorer/grid-list/registry/nf-registry-grid-list-viewer.js': 'components/explorer/grid-list/registry/nf-registry-grid-list-viewer.js',
             'nifi-registry/components/explorer/grid-list/registry/nf-registry-bucket-grid-list-viewer.js': 'components/explorer/grid-list/registry/nf-registry-bucket-grid-list-viewer.js',

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/6c48025c/nifi-registry-web-ui/src/main/webapp/theming/_helperClasses.scss
----------------------------------------------------------------------
diff --git a/nifi-registry-web-ui/src/main/webapp/theming/_helperClasses.scss b/nifi-registry-web-ui/src/main/webapp/theming/_helperClasses.scss
index 91119e5..898a8c7 100644
--- a/nifi-registry-web-ui/src/main/webapp/theming/_helperClasses.scss
+++ b/nifi-registry-web-ui/src/main/webapp/theming/_helperClasses.scss
@@ -50,6 +50,14 @@
     color: $green3;
 }
 
+.nonconfigurable {
+    background: $grey9;
+}
+
+.selected-nonconfigurable {
+    background: repeating-linear-gradient(-45deg, $grey5, $grey5 10px, #fff 10px, #fff 20px) !important;
+}
+
 .nf-registry-button-container {
     position: absolute;
     bottom: 0px;

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/6c48025c/nifi-registry-web-ui/src/main/webapp/theming/_structureElements.scss
----------------------------------------------------------------------
diff --git a/nifi-registry-web-ui/src/main/webapp/theming/_structureElements.scss b/nifi-registry-web-ui/src/main/webapp/theming/_structureElements.scss
index 3e8fa40..3966483 100644
--- a/nifi-registry-web-ui/src/main/webapp/theming/_structureElements.scss
+++ b/nifi-registry-web-ui/src/main/webapp/theming/_structureElements.scss
@@ -16,114 +16,123 @@
  */
 
 body {
-    background: $grey12 url('/nifi-registry/images/registry-logo-web-app.svg') no-repeat center center;
-    background-size: 40%;
+  background: $grey12 url('/nifi-registry/images/registry-logo-web-app.svg') no-repeat center center;
+  background-size: 40%;
 }
 
 #nifi-registry-login-perspective {
-    background: $grey12 url('/nifi-registry/images/registry-logo-web-app.svg') no-repeat center center;
-    background-size: 40%;
-    position: absolute;
-    top: 0px;
-    left: 0px;
-    right: 0px;
-    bottom: 0px;
+  background: $grey12 url('/nifi-registry/images/registry-logo-web-app.svg') no-repeat center center;
+  background-size: 40%;
+  position: absolute;
+  top: 0px;
+  left: 0px;
+  right: 0px;
+  bottom: 0px;
 }
 
 #nifi-registry-not-found-perspective {
-    background: $grey12 url('/nifi-registry/images/registry-logo-web-app.svg') no-repeat center center;
-    background-size: 40%;
-    position: absolute;
-    top: 0px;
-    left: 0px;
-    right: 0px;
-    bottom: 0px;
+  background: $grey12 url('/nifi-registry/images/registry-logo-web-app.svg') no-repeat center center;
+  background-size: 40%;
+  position: absolute;
+  top: 0px;
+  left: 0px;
+  right: 0px;
+  bottom: 0px;
 }
 
 #nf-registry-app-container {
-    margin: 0;
-    width: 100%;
-    height: 100%;
+  margin: 0;
+  width: 100%;
+  height: 100%;
 }
 
 #nifi-registry-logo {
-    height: 44px;
+  height: 44px;
 }
 
 #nifi-registry-alerts-count {
-    border-radius: 50%;
-    background: $warnColor;
-    height: 14px;
-    width: 14px;
-    position: relative;
-    left: 9px;
-    color: #FFFFFF;
-    font-size: 9px;
-    text-align: center;
-    line-height: 14px;
+  border-radius: 50%;
+  background: $warnColor;
+  height: 14px;
+  width: 14px;
+  position: relative;
+  left: 9px;
+  color: #FFFFFF;
+  font-size: 9px;
+  text-align: center;
+  line-height: 14px;
 }
 
 #nifi-registry-toolbar {
-    min-width: 1045px;
-    background-color: #FFFFFF;
-    position: absolute;
-    z-index: 1000;
-    background: $grey11;
+  min-width: 1045px;
+  background-color: #FFFFFF;
+  position: absolute;
+  z-index: 1000;
+  background: $grey11;
 }
 
 #nifi-registry-toolbar .mat-icon-button {
-    color: $grey5;
-    font-size: 20px;
-    margin: 0;
+  color: $grey5;
+  font-size: 20px;
+  margin: 0;
 }
 
-#nifi-registry-toolbar .mat-select-value-text, #nifi-registry-toolbar .mat-select-arrow{
-    color: white;
+#nifi-registry-toolbar .mat-select-value-text, #nifi-registry-toolbar .mat-select-arrow {
+  color: white;
 }
 
-#nifi-registry-toolbar span, #nifi-registry-toolbar .link{
-    color: $grey5;
+#nifi-registry-toolbar span, #nifi-registry-toolbar .link {
+  color: $grey5;
 }
 
 #nf-registry-perspectives-container {
-    position: absolute;
-    top: 64px;
-    left: 0px;
-    right: 0px;
-    bottom: 0px;
-    min-height: 370px;
-    min-width: 1045px;
-    overflow: auto;
-    background: $grey12;
-    background-size: 40%;
+  position: absolute;
+  top: 64px;
+  left: 0px;
+  right: 0px;
+  bottom: 0px;
+  min-height: 370px;
+  min-width: 1045px;
+  overflow: auto;
+  background: $grey12;
+  background-size: 40%;
 }
 
 #current-user {
-    font-family: 'Roboto Slab';
-    font-style: normal;
-    font-weight: normal;
-    font-size: 12px;
-    max-width: 250px;
-    text-overflow: ellipsis;
-    line-height: normal;
-    overflow: hidden;
-    white-space: nowrap;
-    color: $grey5;
+  font-family: 'Roboto Slab';
+  font-style: normal;
+  font-weight: normal;
+  font-size: 12px;
+  max-width: 250px;
+  text-overflow: ellipsis;
+  line-height: normal;
+  overflow: hidden;
+  white-space: nowrap;
+  color: $grey5;
 }
 
 #logout-link-container {
-    font-size: 12px;
-    text-transform:uppercase;
+  font-size: 12px;
+  text-transform: uppercase;
 }
 
 #loading-spinner {
-    position: absolute;
-    top: calc(50% - 50px);
-    left: calc(50% - 50px);
-    z-index: 2;
+  position: absolute;
+  top: calc(50% - 50px);
+  left: calc(50% - 50px);
+  z-index: 2;
 }
 
 mat-sidenav {
-    width: 40%;
-    min-width: 418px;
+  width: 40%;
+  min-width: 418px;
+}
+
+.sidenav-content {
+  position: absolute;
+  bottom: 60px;
+  top: 80px;
+  right: 0px;
+  left: 0px;
+  overflow: auto;
 }

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/6c48025c/nifi-registry-web-ui/src/main/webapp/theming/components/administration/users/_structureElements.scss
----------------------------------------------------------------------
diff --git a/nifi-registry-web-ui/src/main/webapp/theming/components/administration/users/_structureElements.scss b/nifi-registry-web-ui/src/main/webapp/theming/components/administration/users/_structureElements.scss
index 0d5c4ad..2dc41bb 100644
--- a/nifi-registry-web-ui/src/main/webapp/theming/components/administration/users/_structureElements.scss
+++ b/nifi-registry-web-ui/src/main/webapp/theming/components/administration/users/_structureElements.scss
@@ -47,6 +47,12 @@
     right: 10px;
 }
 
+#nf-registry-workflow-bucket-permissions-side-nav-container {
+    position: absolute;
+    bottom: 15px;
+    right: 10px;
+}
+
 #nf-registry-user-group-permissions-side-nav-container {
     position: absolute;
     bottom: 15px;

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/6c48025c/nifi-registry-web-ui/src/main/webapp/theming/components/explorer/grid-list/_structureElements.scss
----------------------------------------------------------------------
diff --git a/nifi-registry-web-ui/src/main/webapp/theming/components/explorer/grid-list/_structureElements.scss b/nifi-registry-web-ui/src/main/webapp/theming/components/explorer/grid-list/_structureElements.scss
index 890889d..f56cd25 100644
--- a/nifi-registry-web-ui/src/main/webapp/theming/components/explorer/grid-list/_structureElements.scss
+++ b/nifi-registry-web-ui/src/main/webapp/theming/components/explorer/grid-list/_structureElements.scss
@@ -29,6 +29,7 @@
     overflow: hidden;
     text-overflow: ellipsis;
     text-align: end;
+    width: 105px;
 }
 
 #nifi-registry-explorer-grid-list-viewer-droplet-container-details {
@@ -38,6 +39,6 @@
 #nifi-registry-explorer-grid-list-viewer-droplet-container-details-change-log {
     position: relative;
     left: 0px;
-    max-height: 230px;
+    max-height: 500px;
     overflow: auto;
 }
\ No newline at end of file


Mime
View raw message