nifi-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From bbe...@apache.org
Subject [3/4] nifi-registry git commit: NIFIREG-30 - Add bucket side nav
Date Thu, 21 Dec 2017 15:46:52 GMT
http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/6c48025c/nifi-registry-web-ui/src/main/webapp/components/administration/users/sidenav/manage-user/nf-registry-manage-user.html
----------------------------------------------------------------------
diff --git a/nifi-registry-web-ui/src/main/webapp/components/administration/users/sidenav/manage-user/nf-registry-manage-user.html b/nifi-registry-web-ui/src/main/webapp/components/administration/users/sidenav/manage-user/nf-registry-manage-user.html
index 1f0feb5..ebc14b9 100644
--- a/nifi-registry-web-ui/src/main/webapp/components/administration/users/sidenav/manage-user/nf-registry-manage-user.html
+++ b/nifi-registry-web-ui/src/main/webapp/components/administration/users/sidenav/manage-user/nf-registry-manage-user.html
@@ -17,137 +17,189 @@ limitations under the License.
 
 <div fxFill>
     <div fxLayout="row" fxLayoutAlign="space-between center" class="pad-top-sm pad-bottom-md pad-left-md pad-right-md">
-        <span class="md-card-title">{{nfRegistryService.user.identity}}</span>
+        <span class="md-card-title ellipsis">{{nfRegistryService.user.identity}}</span>
         <button mat-icon-button (click)="closeSideNav()">
             <mat-icon color="primary">close</mat-icon>
         </button>
     </div>
-    <div class="pad-bottom-md pad-left-md pad-right-md" flex fxLayoutAlign="start center">
-        <mat-input-container flex>
-            <input #usernameInput
-                   matInput
-                   [disabled]="!nfRegistryService.currentUser.resourcePermissions.tenants.canWrite || (nfRegistryService.currentUser.identity === nfRegistryService.user.identity)"
-                   placeholder="Identity/User Name"
-                   value="{{nfRegistryService.user.identity}}"
-                   [(ngModel)]="_username">
-        </mat-input-container>
-        <button [disabled]="nfRegistryService.user.identity === _username || (nfRegistryService.currentUser.identity === nfRegistryService.user.identity)"
-                (click)="updateUserName(usernameInput.value)"
-                class="input-button"
-                color="fds-regular"
-                mat-raised-button>
-            Save
-        </button>
-    </div>
-    <div class="pad-bottom-md pad-left-md pad-right-md" flex fxLayout="column" fxLayoutAlign="space-between start">
-        <div>
+    <div class="sidenav-content">
+        <div class="pad-bottom-md pad-left-md pad-right-md" flex fxLayoutAlign="start center">
+            <mat-input-container flex>
+                <input #usernameInput
+                       matInput
+                       [disabled]="!nfRegistryService.currentUser.resourcePermissions.tenants.canWrite || (nfRegistryService.currentUser.identity === nfRegistryService.user.identity) || !nfRegistryService.user.configurable"
+                       placeholder="Identity/User Name"
+                       value="{{nfRegistryService.user.identity}}"
+                       [(ngModel)]="_username">
+            </mat-input-container>
+            <button [disabled]="nfRegistryService.user.identity === _username || (nfRegistryService.currentUser.identity === nfRegistryService.user.identity) || !nfRegistryService.user.configurable"
+                    (click)="updateUserName(usernameInput.value)"
+                    class="input-button"
+                    color="fds-regular"
+                    mat-raised-button>
+                Save
+            </button>
+        </div>
+        <div class="pad-bottom-md pad-left-md pad-right-md" flex fxLayout="column" fxLayoutAlign="space-between start">
+            <div>
             <span class="header">Special Privileges
-                <i matTooltip="Allows a user to manage NiFi Registry users and groups, buckets, proxies, and policies."
-                          class="pad-left-sm fa fa-question-circle-o help-icon"></i>
+                <i matTooltip="Additional permissions that allow a user to manage or access certain aspects of the registry."
+                   class="pad-left-sm fa fa-question-circle-o help-icon"></i>
             </span>
-        </div>
-        <mat-checkbox [disabled]="!nfRegistryService.currentUser.resourcePermissions.policies.canWrite || (nfRegistryService.currentUser.identity === nfRegistryService.user.identity)" [checked]="nfRegistryService.user.resourcePermissions.buckets.canRead && nfRegistryService.user.resourcePermissions.buckets.canWrite && nfRegistryService.user.resourcePermissions.buckets.canDelete" (change)="toggleUserManageBucketsPrivileges($event)">
-            <span class="description">Can manage buckets</span>
-        </mat-checkbox>
-        <div flex fxLayout="row" fxLayoutAlign="space-around center">
-            <mat-checkbox class="pad-left-md" [disabled]="!nfRegistryService.currentUser.resourcePermissions.policies.canWrite || (nfRegistryService.currentUser.identity === nfRegistryService.user.identity)" [(checked)]="nfRegistryService.user.resourcePermissions.buckets.canRead" (change)="toggleUserManageBucketsPrivileges($event, 'read')">
-                <span class="description">Read</span>
-            </mat-checkbox>
-            <mat-checkbox class="pad-left-md" [disabled]="!nfRegistryService.currentUser.resourcePermissions.policies.canWrite || (nfRegistryService.currentUser.identity === nfRegistryService.user.identity)" [(checked)]="nfRegistryService.user.resourcePermissions.buckets.canWrite" (change)="toggleUserManageBucketsPrivileges($event, 'write')">
-                <span class="description">Write</span>
-            </mat-checkbox>
-            <mat-checkbox class="pad-left-md" [disabled]="!nfRegistryService.currentUser.resourcePermissions.policies.canWrite || (nfRegistryService.currentUser.identity === nfRegistryService.user.identity)" [(checked)]="nfRegistryService.user.resourcePermissions.buckets.canDelete" (change)="toggleUserManageBucketsPrivileges($event, 'delete')">
-                <span class="description">Delete</span>
-            </mat-checkbox>
-        </div>
-        <mat-checkbox [disabled]="!nfRegistryService.currentUser.resourcePermissions.policies.canWrite || (nfRegistryService.currentUser.identity === nfRegistryService.user.identity)" [checked]="nfRegistryService.user.resourcePermissions.tenants.canRead && nfRegistryService.user.resourcePermissions.tenants.canWrite && nfRegistryService.user.resourcePermissions.tenants.canDelete" (change)="toggleUserManageTenantsPrivileges($event)">
-            <span class="description">Can manage users</span>
-        </mat-checkbox>
-        <div flex fxLayout="row" fxLayoutAlign="space-around center">
-            <mat-checkbox class="pad-left-md" [disabled]="!nfRegistryService.currentUser.resourcePermissions.policies.canWrite || (nfRegistryService.currentUser.identity === nfRegistryService.user.identity)" [(checked)]="nfRegistryService.user.resourcePermissions.tenants.canRead" (change)="toggleUserManageTenantsPrivileges($event, 'read')">
-                <span class="description">Read</span>
-            </mat-checkbox>
-            <mat-checkbox class="pad-left-md" [disabled]="!nfRegistryService.currentUser.resourcePermissions.policies.canWrite || (nfRegistryService.currentUser.identity === nfRegistryService.user.identity)" [(checked)]="nfRegistryService.user.resourcePermissions.tenants.canWrite" (change)="toggleUserManageTenantsPrivileges($event, 'write')">
-                <span class="description">Write</span>
-            </mat-checkbox>
-            <mat-checkbox class="pad-left-md" [disabled]="!nfRegistryService.currentUser.resourcePermissions.policies.canWrite || (nfRegistryService.currentUser.identity === nfRegistryService.user.identity)" [(checked)]="nfRegistryService.user.resourcePermissions.tenants.canDelete" (change)="toggleUserManageTenantsPrivileges($event, 'delete')">
-                <span class="description">Delete</span>
+            </div>
+            <mat-checkbox
+                    [disabled]="!nfRegistryService.currentUser.resourcePermissions.policies.canWrite || (nfRegistryService.currentUser.identity === nfRegistryService.user.identity)"
+                    [checked]="nfRegistryService.user.resourcePermissions.buckets.canRead && nfRegistryService.user.resourcePermissions.buckets.canWrite && nfRegistryService.user.resourcePermissions.buckets.canDelete"
+                    (change)="toggleUserManageBucketsPrivileges($event)">
+            <span class="description">Can manage buckets<i
+                    matTooltip="Allow a user to manage all buckets in the registry, as well as provide the user access to all buckets from a connected system (e.g., NiFi)."
+                    class="pad-left-sm fa fa-question-circle-o help-icon"></i></span>
             </mat-checkbox>
-        </div>
-        <mat-checkbox [disabled]="!nfRegistryService.currentUser.resourcePermissions.policies.canWrite || (nfRegistryService.currentUser.identity === nfRegistryService.user.identity)" [checked]="nfRegistryService.user.resourcePermissions.policies.canRead && nfRegistryService.user.resourcePermissions.policies.canWrite && nfRegistryService.user.resourcePermissions.policies.canDelete" (change)="toggleUserManagePoliciesPrivileges($event)">
-            <span class="description">Can manage policies</span>
-        </mat-checkbox>
-        <div flex fxLayout="row" fxLayoutAlign="space-around center">
-            <mat-checkbox class="pad-left-md" [disabled]="!nfRegistryService.currentUser.resourcePermissions.policies.canWrite || (nfRegistryService.currentUser.identity === nfRegistryService.user.identity)" [(checked)]="nfRegistryService.user.resourcePermissions.policies.canRead" (change)="toggleUserManagePoliciesPrivileges($event, 'read')">
-                <span class="description">Read</span>
+            <div flex fxLayout="row" fxLayoutAlign="space-around center">
+                <mat-checkbox class="pad-left-md"
+                              [disabled]="!nfRegistryService.currentUser.resourcePermissions.policies.canWrite || (nfRegistryService.currentUser.identity === nfRegistryService.user.identity)"
+                              [(checked)]="nfRegistryService.user.resourcePermissions.buckets.canRead"
+                              (change)="toggleUserManageBucketsPrivileges($event, 'read')">
+                    <span class="description">Read</span>
+                </mat-checkbox>
+                <mat-checkbox class="pad-left-md"
+                              [disabled]="!nfRegistryService.currentUser.resourcePermissions.policies.canWrite || (nfRegistryService.currentUser.identity === nfRegistryService.user.identity)"
+                              [(checked)]="nfRegistryService.user.resourcePermissions.buckets.canWrite"
+                              (change)="toggleUserManageBucketsPrivileges($event, 'write')">
+                    <span class="description">Write</span>
+                </mat-checkbox>
+                <mat-checkbox class="pad-left-md"
+                              [disabled]="!nfRegistryService.currentUser.resourcePermissions.policies.canWrite || (nfRegistryService.currentUser.identity === nfRegistryService.user.identity)"
+                              [(checked)]="nfRegistryService.user.resourcePermissions.buckets.canDelete"
+                              (change)="toggleUserManageBucketsPrivileges($event, 'delete')">
+                    <span class="description">Delete</span>
+                </mat-checkbox>
+            </div>
+            <mat-checkbox
+                    [disabled]="!nfRegistryService.currentUser.resourcePermissions.policies.canWrite || (nfRegistryService.currentUser.identity === nfRegistryService.user.identity)"
+                    [checked]="nfRegistryService.user.resourcePermissions.tenants.canRead && nfRegistryService.user.resourcePermissions.tenants.canWrite && nfRegistryService.user.resourcePermissions.tenants.canDelete"
+                    (change)="toggleUserManageTenantsPrivileges($event)">
+            <span class="description">Can manage users<i
+                    matTooltip="Allow a user to manage all registry users and groups."
+                    class="pad-left-sm fa fa-question-circle-o help-icon"></i></span>
             </mat-checkbox>
-            <mat-checkbox class="pad-left-md" [disabled]="!nfRegistryService.currentUser.resourcePermissions.policies.canWrite || (nfRegistryService.currentUser.identity === nfRegistryService.user.identity)" [(checked)]="nfRegistryService.user.resourcePermissions.policies.canWrite" (change)="toggleUserManagePoliciesPrivileges($event, 'write')">
-                <span class="description">Write</span>
+            <div flex fxLayout="row" fxLayoutAlign="space-around center">
+                <mat-checkbox class="pad-left-md"
+                              [disabled]="!nfRegistryService.currentUser.resourcePermissions.policies.canWrite || (nfRegistryService.currentUser.identity === nfRegistryService.user.identity)"
+                              [(checked)]="nfRegistryService.user.resourcePermissions.tenants.canRead"
+                              (change)="toggleUserManageTenantsPrivileges($event, 'read')">
+                    <span class="description">Read</span>
+                </mat-checkbox>
+                <mat-checkbox class="pad-left-md"
+                              [disabled]="!nfRegistryService.currentUser.resourcePermissions.policies.canWrite || (nfRegistryService.currentUser.identity === nfRegistryService.user.identity)"
+                              [(checked)]="nfRegistryService.user.resourcePermissions.tenants.canWrite"
+                              (change)="toggleUserManageTenantsPrivileges($event, 'write')">
+                    <span class="description">Write</span>
+                </mat-checkbox>
+                <mat-checkbox class="pad-left-md"
+                              [disabled]="!nfRegistryService.currentUser.resourcePermissions.policies.canWrite || (nfRegistryService.currentUser.identity === nfRegistryService.user.identity)"
+                              [(checked)]="nfRegistryService.user.resourcePermissions.tenants.canDelete"
+                              (change)="toggleUserManageTenantsPrivileges($event, 'delete')">
+                    <span class="description">Delete</span>
+                </mat-checkbox>
+            </div>
+            <mat-checkbox
+                    [disabled]="!nfRegistryService.currentUser.resourcePermissions.policies.canWrite || (nfRegistryService.currentUser.identity === nfRegistryService.user.identity)"
+                    [checked]="nfRegistryService.user.resourcePermissions.policies.canRead && nfRegistryService.user.resourcePermissions.policies.canWrite && nfRegistryService.user.resourcePermissions.policies.canDelete"
+                    (change)="toggleUserManagePoliciesPrivileges($event)">
+            <span class="description">Can manage policies<i
+                    matTooltip="Allow a user to grant all registry users read, write, and delete permission to a bucket."
+                    class="pad-left-sm fa fa-question-circle-o help-icon"></i></span>
             </mat-checkbox>
-            <mat-checkbox class="pad-left-md" [disabled]="!nfRegistryService.currentUser.resourcePermissions.policies.canWrite || (nfRegistryService.currentUser.identity === nfRegistryService.user.identity)" [(checked)]="nfRegistryService.user.resourcePermissions.policies.canDelete" (change)="toggleUserManagePoliciesPrivileges($event, 'delete')">
-                <span class="description">Delete</span>
+            <div flex fxLayout="row" fxLayoutAlign="space-around center">
+                <mat-checkbox class="pad-left-md"
+                              [disabled]="!nfRegistryService.currentUser.resourcePermissions.policies.canWrite || (nfRegistryService.currentUser.identity === nfRegistryService.user.identity)"
+                              [(checked)]="nfRegistryService.user.resourcePermissions.policies.canRead"
+                              (change)="toggleUserManagePoliciesPrivileges($event, 'read')">
+                    <span class="description">Read</span>
+                </mat-checkbox>
+                <mat-checkbox class="pad-left-md"
+                              [disabled]="!nfRegistryService.currentUser.resourcePermissions.policies.canWrite || (nfRegistryService.currentUser.identity === nfRegistryService.user.identity)"
+                              [(checked)]="nfRegistryService.user.resourcePermissions.policies.canWrite"
+                              (change)="toggleUserManagePoliciesPrivileges($event, 'write')">
+                    <span class="description">Write</span>
+                </mat-checkbox>
+                <mat-checkbox class="pad-left-md"
+                              [disabled]="!nfRegistryService.currentUser.resourcePermissions.policies.canWrite || (nfRegistryService.currentUser.identity === nfRegistryService.user.identity)"
+                              [(checked)]="nfRegistryService.user.resourcePermissions.policies.canDelete"
+                              (change)="toggleUserManagePoliciesPrivileges($event, 'delete')">
+                    <span class="description">Delete</span>
+                </mat-checkbox>
+            </div>
+            <mat-checkbox
+                    [disabled]="!nfRegistryService.currentUser.resourcePermissions.policies.canWrite || (nfRegistryService.currentUser.identity === nfRegistryService.user.identity)"
+                    [checked]="nfRegistryService.user.resourcePermissions.proxy.canWrite"
+                    (change)="toggleUserManageProxyPrivileges($event)">
+            <span class="description">Can proxy user requests<i
+                    matTooltip="Allow a connected system (e.g., NiFi) to process requests of authorized users of that system."
+                    class="pad-left-sm fa fa-question-circle-o help-icon"></i></span>
             </mat-checkbox>
         </div>
-        <mat-checkbox [disabled]="!nfRegistryService.currentUser.resourcePermissions.policies.canWrite || (nfRegistryService.currentUser.identity === nfRegistryService.user.identity)" [checked]="nfRegistryService.user.resourcePermissions.proxy.canWrite" (change)="toggleUserManageProxyPrivileges($event)">
-            <span class="description">Can proxy user requests</span>
-        </mat-checkbox>
-    </div>
-    <mat-button-toggle-group name="nifi-registry-manage-user-perspective" class="pad-left-md tab-toggle-group">
-        <mat-button-toggle [checked]="manageUserPerspective === 'membership'"
-                           value="membership"
-                           class="uppercase"
-                           (change)="manageUserPerspective = 'membership'"
-                           i18n="Group membership tab, user management sidenav|View the groups to which this user belongs.@@nf-admin-user-management-sidenav-membership-tab-title">
-            Membership
-        </mat-button-toggle>
-    </mat-button-toggle-group>
-    <div *ngIf="manageUserPerspective === 'membership'">
-        <div *ngIf="nfRegistryService.user.userGroups" fxFlex class="pad-top-md pad-bottom-sm pad-left-md pad-right-md">
-            <div flex fxLayout="row" fxLayoutAlign="space-between center">
-                <span class="md-card-title">Membership ({{nfRegistryService.user.userGroups.length}})</span>
-                <button color="fds-secondary"
-                        [disabled]="!nfRegistryService.currentUser.resourcePermissions.tenants.canWrite"
-                        mat-raised-button
-                        (click)="addUserToGroups()">
-                    Add To Group
-                </button>
-            </div>
-            <div id="nifi-registry-user-membership-list-container-column-header" fxLayout="row"
-                 fxLayoutAlign="space-between center" class="td-data-table">
-                <div class="td-data-table-column" (click)="sortGroups(column)"
-                     *ngFor="let column of nfRegistryService.userGroupsColumns"
-                     fxFlex="{{column.width}}">
-                    {{column.label}}
-                    <i *ngIf="column.active && column.sortable && column.sortOrder === 'ASC'" class="fa fa-caret-up"
-                       aria-hidden="true"></i>
-                    <i *ngIf="column.active && column.sortable && column.sortOrder === 'DESC'" class="fa fa-caret-down"
-                       aria-hidden="true"></i>
+        <mat-button-toggle-group name="nifi-registry-manage-user-perspective" class="pad-left-md tab-toggle-group">
+            <mat-button-toggle [checked]="manageUserPerspective === 'membership'"
+                               value="membership"
+                               class="uppercase"
+                               (change)="manageUserPerspective = 'membership'"
+                               i18n="Group membership tab, user management sidenav|View the groups to which this user belongs.@@nf-admin-user-management-sidenav-membership-tab-title">
+                Membership
+            </mat-button-toggle>
+        </mat-button-toggle-group>
+        <div *ngIf="manageUserPerspective === 'membership'">
+            <div *ngIf="nfRegistryService.user.userGroups" class="pad-top-md pad-bottom-sm pad-left-md pad-right-md">
+                <div flex fxLayout="row" fxLayoutAlign="space-between center">
+                    <span class="md-card-title">Membership ({{nfRegistryService.user.userGroups.length}})</span>
+                    <button color="fds-secondary"
+                            [disabled]="!nfRegistryService.currentUser.resourcePermissions.tenants.canWrite"
+                            mat-raised-button
+                            (click)="addUserToGroups()">
+                        Add To Group
+                    </button>
                 </div>
-            </div>
-            <div id="nifi-registry-user-membership-list-container">
-                <div fxLayout="row" fxLayoutAlign="space-between center" class="td-data-table-row"
-                     [ngClass]="{'selected' : row.checked}" *ngFor="let row of filteredUserGroups"
-                     (click)="row.checked = !row.checked">
-                    <div class="td-data-table-cell" *ngFor="let column of nfRegistryService.userGroupsColumns"
+                <div id="nifi-registry-user-membership-list-container-column-header" fxLayout="row"
+                     fxLayoutAlign="space-between center" class="td-data-table">
+                    <div class="td-data-table-column" (click)="sortGroups(column)"
+                         *ngFor="let column of nfRegistryService.userGroupsColumns"
                          fxFlex="{{column.width}}">
-                        <div matTooltip="{{column.format ? column.format(row[column.name]) : row[column.name]}}">
-                            <i class="fa fa-users push-right-sm" aria-hidden="true"></i>{{column.format ? column.format(row[column.name]) : row[column.name]}}
-                        </div>
+                        {{column.label}}
+                        <i *ngIf="column.active && column.sortable && column.sortOrder === 'ASC'" class="fa fa-caret-up"
+                           aria-hidden="true"></i>
+                        <i *ngIf="column.active && column.sortable && column.sortOrder === 'DESC'"
+                           class="fa fa-caret-down"
+                           aria-hidden="true"></i>
                     </div>
-                    <div class="td-data-table-cell">
-                        <div>
-                            <button (click)="removeUserFromGroup(row);row.checked = !row.checked;"
-                                    matTooltip="'Remove user from group'" mat-icon-button color="accent"
-                                    *ngIf="nfRegistryService.currentUser.resourcePermissions.tenants.canWrite">
-                                <i class="fa fa-minus-circle" aria-hidden="true"></i>
-                            </button>
+                </div>
+                <div id="nifi-registry-user-membership-list-container">
+                    <div fxLayout="row" fxLayoutAlign="space-between center" class="td-data-table-row"
+                         [ngClass]="{'selected' : row.checked}" *ngFor="let row of filteredUserGroups"
+                         (click)="row.checked = !row.checked">
+                        <div class="td-data-table-cell" *ngFor="let column of nfRegistryService.userGroupsColumns"
+                             fxFlex="{{column.width}}">
+                            <div class="ellipsis"
+                                 matTooltip="{{column.format ? column.format(row[column.name]) : row[column.name]}}">
+                                <i class="fa fa-users push-right-sm" aria-hidden="true"></i>{{column.format ?
+                                column.format(row[column.name]) : row[column.name]}}
+                            </div>
+                        </div>
+                        <div class="td-data-table-cell">
+                            <div>
+                                <button (click)="removeUserFromGroup(row);row.checked = !row.checked;"
+                                        [disabled]="!row.configurable"
+                                        matTooltip="'Remove user from group'" mat-icon-button color="accent">
+                                    <i class="fa fa-minus-circle" aria-hidden="true"></i>
+                                </button>
+                            </div>
                         </div>
                     </div>
                 </div>
-            </div>
-            <div class="mat-padding" *ngIf="nfRegistryService.user.userGroups.length === 0" layout="row"
-                 layout-align="center center">
-                <h3>This user does not belong to any groups yet.</h3>
+                <div class="mat-padding" *ngIf="nfRegistryService.user.userGroups.length === 0" layout="row"
+                     layout-align="center center">
+                    <h3>This user does not belong to any groups yet.</h3>
+                </div>
             </div>
         </div>
     </div>

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/6c48025c/nifi-registry-web-ui/src/main/webapp/components/administration/users/sidenav/manage-user/nf-registry-manage-user.js
----------------------------------------------------------------------
diff --git a/nifi-registry-web-ui/src/main/webapp/components/administration/users/sidenav/manage-user/nf-registry-manage-user.js b/nifi-registry-web-ui/src/main/webapp/components/administration/users/sidenav/manage-user/nf-registry-manage-user.js
index 59aca5f..d9c305d 100644
--- a/nifi-registry-web-ui/src/main/webapp/components/administration/users/sidenav/manage-user/nf-registry-manage-user.js
+++ b/nifi-registry-web-ui/src/main/webapp/components/administration/users/sidenav/manage-user/nf-registry-manage-user.js
@@ -66,7 +66,7 @@ NfRegistryManageUser.prototype = {
         this.nfRegistryService.sidenav.open();
 
         // subscribe to the route params
-        self.route.params
+        this.$subscription = self.route.params
             .switchMap(function (params) {
                 return self.nfRegistryApi.getUser(params['userId']);
             })
@@ -82,6 +82,7 @@ NfRegistryManageUser.prototype = {
      */
     ngOnDestroy: function () {
         this.nfRegistryService.sidenav.close();
+        this.$subscription.unsubscribe();
     },
 
     /**
@@ -152,7 +153,7 @@ NfRegistryManageUser.prototype = {
                                     // resource exists, let's filter out the current user and update it
                                     policy.users = policy.users.filter(function (user) {
                                         return (user.identifier !== self.nfRegistryService.user.identifier) ? true : false;
-                                    })
+                                    });
                                     self.nfRegistryApi.putPolicyActionResource(policy.identifier, policy.action,
                                         policy.resource, policy.users, policy.userGroups).subscribe(
                                         function (response) {
@@ -232,7 +233,7 @@ NfRegistryManageUser.prototype = {
                                     // resource exists, let's filter out the current user and update it
                                     policy.users = policy.users.filter(function (user) {
                                         return (user.identifier !== self.nfRegistryService.user.identifier) ? true : false;
-                                    })
+                                    });
                                     self.nfRegistryApi.putPolicyActionResource(policy.identifier, policy.action,
                                         policy.resource, policy.users, policy.userGroups).subscribe(
                                         function (response) {
@@ -312,7 +313,7 @@ NfRegistryManageUser.prototype = {
                                     // resource exists, let's filter out the current user and update it
                                     policy.users = policy.users.filter(function (user) {
                                         return (user.identifier !== self.nfRegistryService.user.identifier) ? true : false;
-                                    })
+                                    });
                                     self.nfRegistryApi.putPolicyActionResource(policy.identifier, policy.action,
                                         policy.resource, policy.users, policy.userGroups).subscribe(
                                         function (response) {
@@ -418,7 +419,8 @@ NfRegistryManageUser.prototype = {
         var self = this;
         this.dialog.open(NfRegistryAddUserToGroups, {
             data: {
-                user: this.nfRegistryService.user
+                user: this.nfRegistryService.user,
+                disableClose: true
             }
         }).afterClosed().subscribe(function () {
             self.nfRegistryApi.getUser(self.nfRegistryService.user.identifier)

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/6c48025c/nifi-registry-web-ui/src/main/webapp/components/administration/workflow/buckets/permissions/nf-registry-bucket-permissions.html
----------------------------------------------------------------------
diff --git a/nifi-registry-web-ui/src/main/webapp/components/administration/workflow/buckets/permissions/nf-registry-bucket-permissions.html b/nifi-registry-web-ui/src/main/webapp/components/administration/workflow/buckets/permissions/nf-registry-bucket-permissions.html
deleted file mode 100644
index bae5218..0000000
--- a/nifi-registry-web-ui/src/main/webapp/components/administration/workflow/buckets/permissions/nf-registry-bucket-permissions.html
+++ /dev/null
@@ -1,114 +0,0 @@
-<!--
-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.
--->
-
-<div fxFill>
-    <div fxLayout="row" fxLayoutAlign="space-between center" class="pad-top-sm pad-bottom-md pad-left-md pad-right-md">
-        <span *ngIf="nfRegistryService.bucket.identifier" class="md-card-title">{{nfRegistryService.bucket.name}}</span>
-        <button mat-icon-button (click)="closeSideNav()">
-            <mat-icon color="primary">close</mat-icon>
-        </button>
-    </div>
-    <div class="pad-bottom-md pad-left-md pad-right-md" flex fxLayoutAlign="start center">
-        <mat-input-container floatPlaceholder="always" flex>
-            <input matInput placeholder="Bucket Name" value="{{nfRegistryService.bucket.name}}">
-        </mat-input-container>
-        <button class="input-button" color="fds-regular" mat-raised-button>
-            Save
-        </button>
-    </div>
-    <!--<div id="nifi-registry-bucket-permissions-container" class="mat-elevation-z5">-->
-        <!--<div fxFlex class="pad-top-md pad-bottom-sm pad-left-md pad-right-md">-->
-            <!--<span class="md-card-title">Policies ({{nfRegistryService.bucket.authorizedActions.length}})</span>-->
-            <!--<div id="nifi-registry-bucket-permissions-list-container-column-header" fxLayout="row"-->
-                 <!--fxLayoutAlign="space-between center" class="td-data-table">-->
-                <!--<div class="td-data-table-column" (click)="nfRegistryService.sortBuckets(column)"-->
-                     <!--*ngFor="let column of nfRegistryService.bucketColumns"-->
-                     <!--fxFlex="{{column.width}}">-->
-                    <!--{{column.label}}-->
-                    <!--<i *ngIf="column.active && column.sortable && column.sortOrder === 'ASC'" class="fa fa-caret-up"-->
-                       <!--aria-hidden="true"></i>-->
-                    <!--<i *ngIf="column.active && column.sortable && column.sortOrder === 'DESC'" class="fa fa-caret-down"-->
-                       <!--aria-hidden="true"></i>-->
-                <!--</div>-->
-                <!--<div class="td-data-table-column">-->
-                    <!--<div fxLayout="row" fxLayoutAlign="end center">-->
-                        <!--<mat-checkbox class="pad-left-sm" [(ngModel)]="nfRegistryService.allBucketsSelected"-->
-                                      <!--(checked)="nfRegistryService.allBucketsSelected"-->
-                                      <!--(change)="nfRegistryService.toggleBucketsSelectAll()"></mat-checkbox>-->
-                    <!--</div>-->
-                <!--</div>-->
-            <!--</div>-->
-            <!--<div id="nifi-registry-bucket-permissions-list-container">-->
-                <!--<div fxLayout="row" fxLayoutAlign="space-between center" class="td-data-table-row"-->
-                     <!--[ngClass]="{'selected' : row.checked}" *ngFor="let row of nfRegistryService.filteredBuckets"-->
-                     <!--(click)="row.checked = !row.checked;nfRegistryService.determineAllBucketsSelectedState()">-->
-                    <!--<div class="td-data-table-cell" *ngFor="let column of nfRegistryService.bucketColumns"-->
-                         <!--fxFlex="{{column.width}}">-->
-                        <!--<div matTooltip="{{column.format ? column.format(row[column.name]) : row[column.name]}}">-->
-                            <!--{{column.format ? column.format(row[column.name]) : row[column.name]}}-->
-                        <!--</div>-->
-                    <!--</div>-->
-                    <!--<div class="td-data-table-cell">-->
-                        <!--<div>-->
-                            <!--<div *ngIf="bucketActions.length <= 4" fxLayout="row" fxLayoutAlign="end center">-->
-                                <!--<button (click)="nfRegistryService.executeBucketAction(action, row);row.checked = !row.checked;"-->
-                                        <!--*ngFor="let action of bucketActions"-->
-                                        <!--matTooltip="{{action.tooltip}}" mat-icon-button color="accent"-->
-                                        <!--[disabled]="action.disabled ? '' : null">-->
-                                    <!--<i class="{{action.icon}}" aria-hidden="true"></i>-->
-                                <!--</button>-->
-                                <!--<mat-checkbox class="pad-left-sm" [(ngModel)]="row.checked" [checked]="row.checked"-->
-                                              <!--(change)="nfRegistryService.determineAllBucketsSelectedState()"-->
-                                              <!--(click)="row.checked = !row.checked;nfRegistryService.determineAllBucketsSelectedState()"></mat-checkbox>-->
-                            <!--</div>-->
-                            <!--<div *ngIf="bucketActions.length > 4" fxLayout="row" fxLayoutAlign="end center">-->
-                                <!--<button (click)="row.checked = !row.checked" matTooltip="Actions" mat-icon-button-->
-                                        <!--[matMenuTriggerFor]="bucketTableActionMenu">-->
-                                    <!--<i class="fa fa-ellipsis-h" aria-hidden="true"></i>-->
-                                <!--</button>-->
-                                <!--<mat-menu #bucketTableActionMenu="matMenu" [overlapTrigger]="false">-->
-                                    <!--<button (click)="nfRegistryService.executeBucketAction(action, row);row.checked = !row.checked;"-->
-                                            <!--*ngFor="let action of bucketActions"-->
-                                            <!--matTooltip="{{action.tooltip}}" mat-menu-item-->
-                                            <!--[disabled]="action.disabled ? '' : null">-->
-                                        <!--<i class="{{action.icon}}" aria-hidden="true"></i>-->
-                                        <!--<span>{{action.name}}</span>-->
-                                    <!--</button>-->
-                                <!--</mat-menu>-->
-                                <!--<mat-checkbox [(ngModel)]="row.checked" [checked]="row.checked"-->
-                                              <!--(change)="nfRegistryService.determineAllBucketsSelectedState()"-->
-                                              <!--(click)="row.checked = !row.checked;nfRegistryService.determineAllBucketsSelectedState()"></mat-checkbox>-->
-                            <!--</div>-->
-                        <!--</div>-->
-                        <!--<div *ngIf="!bucketActions" fxLayout="row" fxLayoutAlign="end center">-->
-                            <!--<mat-checkbox [(ngModel)]="row.checked" [checked]="row.checked"-->
-                                          <!--(change)="nfRegistryService.determineAllBucketsSelectedState(row)"-->
-                                          <!--(click)="row.checked = !row.checked;nfRegistryService.determineAllBucketsSelectedState()"></mat-checkbox>-->
-                        <!--</div>-->
-                    <!--</div>-->
-                <!--</div>-->
-            <!--</div>-->
-            <!--<div class="mat-padding" *ngIf="nfRegistryService.filteredBuckets.length === 0" layout="row"-->
-                 <!--layout-align="center center">-->
-                <!--<h3>No results to display.</h3>-->
-            <!--</div>-->
-        <!--</div>-->
-    <!--</div>-->
-    <button id="nf-registry-workflow-bucket-permissions-side-nav-container" mat-raised-button color="fds-primary"
-            (click)="closeSideNav()">Close
-    </button>
-</div>

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/6c48025c/nifi-registry-web-ui/src/main/webapp/components/administration/workflow/buckets/permissions/nf-registry-bucket-permissions.js
----------------------------------------------------------------------
diff --git a/nifi-registry-web-ui/src/main/webapp/components/administration/workflow/buckets/permissions/nf-registry-bucket-permissions.js b/nifi-registry-web-ui/src/main/webapp/components/administration/workflow/buckets/permissions/nf-registry-bucket-permissions.js
deleted file mode 100644
index 74f5689..0000000
--- a/nifi-registry-web-ui/src/main/webapp/components/administration/workflow/buckets/permissions/nf-registry-bucket-permissions.js
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * 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.
- */
-var ngCore = require('@angular/core');
-var NfRegistryService = require('nifi-registry/services/nf-registry.service.js');
-var NfRegistryApi = require('nifi-registry/services/nf-registry.api.js');
-var ngRouter = require('@angular/router');
-
-/**
- * NfRegistryBucketPermissions constructor.
- *
- * @param nfRegistryApi         The api service.
- * @param nfRegistryService     The nf-registry.service module.
- * @param ActivatedRoute        The angular activated route module.
- * @param Router                The angular router module.
- * @constructor
- */
-function NfRegistryBucketPermissions(nfRegistryApi, nfRegistryService, ActivatedRoute, Router) {
-    this.nfRegistryService = nfRegistryService;
-    this.nfRegistryApi = nfRegistryApi;
-    this.route = ActivatedRoute;
-    this.router = Router;
-};
-
-NfRegistryBucketPermissions.prototype = {
-    constructor: NfRegistryBucketPermissions,
-
-    /**
-     * Initialize the component.
-     */
-    ngOnInit: function () {
-        var self = this;
-        this.nfRegistryService.sidenav.open();
-        this.route.params
-            .switchMap(function (params) {
-                return self.nfRegistryApi.getBucket(params['bucketId']);
-            })
-            .subscribe(function (bucket) {
-                self.nfRegistryService.bucket = bucket;
-            });
-    },
-
-    /**
-     * Destroy the component.
-     */
-    ngOnDestroy: function () {
-        this.nfRegistryService.sidenav.close();
-        this.nfRegistryService.bucket = {};
-    },
-
-    /**
-     * Navigate to administer the buckets of the current registry.
-     */
-    closeSideNav: function () {
-        this.router.navigateByUrl('/nifi-registry/administration/workflow');
-    }
-};
-
-NfRegistryBucketPermissions.annotations = [
-    new ngCore.Component({
-        template: require('./nf-registry-bucket-permissions.html!text')
-    })
-];
-
-NfRegistryBucketPermissions.parameters = [
-    NfRegistryApi,
-    NfRegistryService,
-    ngRouter.ActivatedRoute,
-    ngRouter.Router
-];
-
-module.exports = NfRegistryBucketPermissions;

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/6c48025c/nifi-registry-web-ui/src/main/webapp/components/administration/workflow/dialogs/add-policy-to-bucket/nf-registry-add-policy-to-bucket.html
----------------------------------------------------------------------
diff --git a/nifi-registry-web-ui/src/main/webapp/components/administration/workflow/dialogs/add-policy-to-bucket/nf-registry-add-policy-to-bucket.html b/nifi-registry-web-ui/src/main/webapp/components/administration/workflow/dialogs/add-policy-to-bucket/nf-registry-add-policy-to-bucket.html
new file mode 100644
index 0000000..8c89010
--- /dev/null
+++ b/nifi-registry-web-ui/src/main/webapp/components/administration/workflow/dialogs/add-policy-to-bucket/nf-registry-add-policy-to-bucket.html
@@ -0,0 +1,99 @@
+<!--
+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.
+-->
+
+<div id="nifi-registry-admin-create-bucket-dialog">
+    <div class="pad-bottom-md" fxLayout="row" fxLayoutAlign="space-between center">
+        <span class="md-card-title">New Policy</span>
+        <button mat-icon-button (click)="cancel()">
+            <mat-icon color="primary">close</mat-icon>
+        </button>
+    </div>
+    <div class="pad-bottom-md">
+        <div id="nifi-registry-users-administration-list-container-column-header" class="td-data-table">
+            <div class="td-data-table-column" (click)="sortUserAndGroups(column)"
+                 *ngFor="let column of nfRegistryService.userGroupsColumns"
+                 fxFlex="{{column.width}}">
+                {{column.label}}
+                <i *ngIf="column.active && column.sortable && column.sortOrder === 'ASC'" class="fa fa-caret-up"
+                   aria-hidden="true"></i>
+                <i *ngIf="column.active && column.sortable && column.sortOrder === 'DESC'" class="fa fa-caret-down"
+                   aria-hidden="true"></i>
+            </div>
+            <div class="td-data-table-column"></div>
+        </div>
+        <div id="nifi-registry-add-selected-users-to-group-list-container">
+            <div [ngClass]="{'selected' : row.checked}" *ngFor="let row of filteredUserGroups"
+                 (click)="userOrGroup = row; userOrGroup.type = 'group';">
+                <div *ngFor="let column of nfRegistryService.userGroupsColumns" fxLayout="row"
+                     fxLayoutAlign="space-between center" class="td-data-table-row">
+                    <div class="td-data-table-cell" fxFlex="{{column.width}}">
+                        <div>
+                            <i class="fa fa-users push-right-sm" aria-hidden="true"></i>{{column.format ?
+                            column.format(row[column.name]) : row[column.name]}}
+                        </div>
+                    </div>
+                    <div class="td-data-table-cell">
+                        <mat-checkbox [checked]="row[column.name] === userOrGroup.identity"
+                                      (click)="userOrGroup = row; userOrGroup.type = 'group';">
+                        </mat-checkbox>
+                    </div>
+                </div>
+            </div>
+            <div [ngClass]="{'selected' : row.checked}" *ngFor="let row of filteredUsers"
+                 (click)="userOrGroup = row; userOrGroup.type = 'user';">
+                <div *ngFor="let column of nfRegistryService.userGroupsColumns" fxLayout="row"
+                     fxLayoutAlign="space-between center" class="td-data-table-row">
+                    <div class="td-data-table-cell" fxFlex="{{column.width}}">
+                        <div>
+                            {{column.format ? column.format(row[column.name]) : row[column.name]}}
+                        </div>
+                    </div>
+                    <div class="td-data-table-cell">
+                        <mat-checkbox [checked]="row[column.name] === userOrGroup.identity"
+                                      (click)="userOrGroup = row; userOrGroup.type = 'user';">
+                        </mat-checkbox>
+                    </div>
+                </div>
+            </div>
+        </div>
+    </div>
+    <div flex fxLayout="row" fxLayoutAlign="start center" class="pad-bottom-md">
+        <mat-checkbox [(checked)]="readCheckbox.checked && writeCheckbox.checked && deleteCheckbox.checked" (change)="toggleAllPermissions($event)">
+            <span class="description">All</span>
+        </mat-checkbox>
+        <mat-checkbox [(checked)]="readCheckbox.checked" #readCheckbox class="pad-left-md">
+            <span class="description">Read</span>
+        </mat-checkbox>
+        <mat-checkbox [(checked)]="writeCheckbox.checked" #writeCheckbox class="pad-left-md">
+            <span class="description">Write</span>
+        </mat-checkbox>
+        <mat-checkbox [(checked)]="deleteCheckbox.checked" #deleteCheckbox class="pad-left-md">
+            <span class="description">Delete</span>
+        </mat-checkbox>
+    </div>
+    <div fxLayout="row">
+        <span fxFlex></span>
+        <button (click)="cancel()" color="fds-regular" mat-raised-button
+                i18n="Cancel creation of new bucket policy|A button for cancelling the creation of a new bucket policy in the registry.@@nf-admin-workflow-cancel-bucket-policy-creation-button">
+            Cancel
+        </button>
+        <button [disabled]="(!userOrGroup.identity) || (!readCheckbox.checked && !writeCheckbox.checked && !deleteCheckbox.checked)" class="push-left-sm" (click)="applyPolicy()" color="fds-primary" mat-raised-button
+                i18n="Apply new bucket policy button|A button for applying a new bucket policy in the registry.@@nf-admin-workflow-apply-policy-to-bucket-button">
+            Apply
+        </button>
+    </div>
+</div>
\ 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/components/administration/workflow/dialogs/add-policy-to-bucket/nf-registry-add-policy-to-bucket.js
----------------------------------------------------------------------
diff --git a/nifi-registry-web-ui/src/main/webapp/components/administration/workflow/dialogs/add-policy-to-bucket/nf-registry-add-policy-to-bucket.js b/nifi-registry-web-ui/src/main/webapp/components/administration/workflow/dialogs/add-policy-to-bucket/nf-registry-add-policy-to-bucket.js
new file mode 100644
index 0000000..118da49
--- /dev/null
+++ b/nifi-registry-web-ui/src/main/webapp/components/administration/workflow/dialogs/add-policy-to-bucket/nf-registry-add-policy-to-bucket.js
@@ -0,0 +1,381 @@
+/*
+ * 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.
+ */
+
+var rxjs = require('rxjs/Observable');
+var ngCore = require('@angular/core');
+var NfRegistryService = require('nifi-registry/services/nf-registry.service.js');
+var NfRegistryApi = require('nifi-registry/services/nf-registry.api.js');
+var ngMaterial = require('@angular/material');
+var ngRouter = require('@angular/router');
+var covalentCore = require('@covalent/core');
+var fdsSnackBarsModule = require('@fluid-design-system/snackbars');
+
+/**
+ * NfRegistryAddPolicyToBucket constructor.
+ *
+ * @param nfRegistryApi         The api service.
+ * @param tdDataTableService    The covalent data table service module.
+ * @param fdsSnackBarService    The FDS snack bar service module.
+ * @param nfRegistryService     The nf-registry.service module.
+ * @param activatedRoute        The angular route module.
+ * @param matDialogRef          The angular material dialog ref.
+ * @param data                  The data passed into this component.
+ * @constructor
+ */
+function NfRegistryAddPolicyToBucket(nfRegistryApi, tdDataTableService, fdsSnackBarService, nfRegistryService, activatedRoute, matDialogRef, data) {
+    this.users = [];
+    this.groups = [];
+    this.userOrGroup = {};
+    this.filteredGroups = [];
+    this.filteredUsers = [];
+    this.usersSearchTerms = [];
+    this.userGroupsSearchTerms = [];
+    // Services
+    this.dataTableService = tdDataTableService;
+    this.snackBarService = fdsSnackBarService;
+    this.nfRegistryService = nfRegistryService;
+    this.route = activatedRoute;
+    this.nfRegistryApi = nfRegistryApi;
+    this.dialogRef = matDialogRef;
+    this.data = data;
+};
+
+NfRegistryAddPolicyToBucket.prototype = {
+    constructor: NfRegistryAddPolicyToBucket,
+
+    /**
+     * Initialize the component.
+     */
+    ngOnInit: function () {
+        var self = this;
+        this.route.params
+            .switchMap(function (params) {
+                return new rxjs.Observable.forkJoin(
+                    self.nfRegistryApi.getUsers(),
+                    self.nfRegistryApi.getUserGroups()
+                );
+            })
+            .subscribe(function (response) {
+                self.users = response[0];
+                self.users = self.users.filter(function (user) {
+                    return (self.data.users.indexOf(user.identity) < 0) ? true : false;
+                });
+                self.groups = response[1];
+                self.groups = self.groups.filter(function (group) {
+                    return (self.data.groups.indexOf(group.identity) < 0) ? true : false;
+                });
+
+                self.filterUsersAndGroups();
+            });
+    },
+
+    /**
+     * Filter users and groups.
+     *
+     * @param {string} [sortBy]       The column name to sort `userGroupsColumns` by.
+     * @param {string} [sortOrder]    The order. Either 'ASC' or 'DES'
+     */
+    filterUsersAndGroups: function (sortBy, sortOrder) {
+        // if `sortOrder` is `undefined` then use 'ASC'
+        if (sortOrder === undefined) {
+            sortOrder = 'ASC'
+        }
+        // if `sortBy` is `undefined` then find the first sortable column in `dropletColumns`
+        if (sortBy === undefined) {
+            var arrayLength = this.nfRegistryService.userGroupsColumns.length;
+            for (var i = 0; i < arrayLength; i++) {
+                if (this.nfRegistryService.userGroupsColumns[i].sortable === true) {
+                    sortBy = this.nfRegistryService.userGroupsColumns[i].name;
+                    //only one column can be actively sorted so we reset all to inactive
+                    this.nfRegistryService.userGroupsColumns.forEach(function (c) {
+                        c.active = false;
+                    });
+                    //and set this column as the actively sorted column
+                    this.nfRegistryService.userGroupsColumns[i].active = true;
+                    this.nfRegistryService.userGroupsColumns[i].sortOrder = sortOrder;
+                    break;
+                }
+            }
+        }
+
+        var newUserGroupsData = this.groups;
+
+        for (var i = 0; i < this.userGroupsSearchTerms.length; i++) {
+            newUserGroupsData = this.nfRegistryService.filterData(newUserGroupsData, this.userGroupsSearchTerms[i], true);
+        }
+
+        newUserGroupsData = this.dataTableService.sortData(newUserGroupsData, sortBy, sortOrder);
+        this.filteredUserGroups = newUserGroupsData;
+
+        var newUsersData = this.users;
+
+        for (var i = 0; i < this.usersSearchTerms.length; i++) {
+            newUsersData = this.nfRegistryService.filterData(newUsersData, this.usersSearchTerms[i], true);
+        }
+
+        newUsersData = this.dataTableService.sortData(newUsersData, sortBy, sortOrder);
+        this.filteredUsers = newUsersData;
+    },
+
+    /**
+     * Sort users and groups.
+     *
+     * @param column    The column to sort by.
+     */
+    sortUserAndGroups: function (column) {
+        if (column.sortable) {
+            var sortBy = column.name;
+            var sortOrder = column.sortOrder = (column.sortOrder === 'ASC') ? 'DESC' : 'ASC';
+            this.filterUsersAndGroups(sortBy, sortOrder);
+        }
+    },
+
+    /**
+     * Create a new policy.
+     */
+    applyPolicy: function () {
+        var self = this;
+        var action = '';
+        var resource = '/buckets';
+        var permissions = [];
+        if (this.readCheckbox.checked) {
+            action = 'read';
+            permissions.push(action);
+            this.nfRegistryApi.getResourcePoliciesById(action, resource, this.nfRegistryService.bucket.identifier).subscribe(function (policy) {
+                action = 'read';
+                if (policy.status && policy.status === 404) {
+                    // resource does NOT exist, let's create it
+                    var users = [];
+                    var groups = [];
+
+                    if (self.userOrGroup.type === 'user') {
+                        users.push(self.userOrGroup);
+                    } else {
+                        groups.push(self.userOrGroup);
+                    }
+
+                    self.nfRegistryApi.postPolicyActionResource(action, resource + '/' + self.nfRegistryService.bucket.identifier, users, groups).subscribe(
+                        function (response) {
+                            // policy created!!!...now update the view
+                            self.nfRegistryApi.getBucket(self.nfRegistryService.bucket.identifier).subscribe(function (response) {
+                                self.nfRegistryService.bucket = response;
+                                var snackBarRef = self.snackBarService.openCoaster({
+                                    title: 'Success',
+                                    message: 'Policy created.',
+                                    verticalPosition: 'bottom',
+                                    horizontalPosition: 'right',
+                                    icon: 'fa fa-check-circle-o',
+                                    color: '#1EB475',
+                                    duration: 3000
+                                });
+                            });
+                        });
+                } else {
+                    // resource exists, let's update it
+                    if (self.userOrGroup.type === 'user') {
+                        policy.users.push(self.userOrGroup);
+                    } else {
+                        policy.userGroups.push(self.userOrGroup);
+                    }
+                    self.nfRegistryApi.putPolicyActionResource(policy.identifier, policy.action,
+                        policy.resource, policy.users, policy.userGroups).subscribe(
+                        function (response) {
+                            // policy updated!!!...now update the view
+                            self.nfRegistryApi.getBucket(self.nfRegistryService.bucket.identifier).subscribe(function (response) {
+                                self.nfRegistryService.bucket = response;
+                                var snackBarRef = self.snackBarService.openCoaster({
+                                    title: 'Success',
+                                    message: 'Policy created.',
+                                    verticalPosition: 'bottom',
+                                    horizontalPosition: 'right',
+                                    icon: 'fa fa-check-circle-o',
+                                    color: '#1EB475',
+                                    duration: 3000
+                                });
+                            });
+                        });
+                }
+            });
+        }
+        if (this.writeCheckbox.checked) {
+            action = 'write';
+            permissions.push(action);
+            this.nfRegistryApi.getResourcePoliciesById(action, resource, this.nfRegistryService.bucket.identifier).subscribe(function (policy) {
+                action = 'write';
+                if (policy.status && policy.status === 404) {
+                    // resource does NOT exist, let's create it
+                    var users = [];
+                    var groups = [];
+
+                    if (self.userOrGroup.type === 'user') {
+                        users.push(self.userOrGroup);
+                    } else {
+                        groups.push(self.userOrGroup);
+                    }
+
+                    self.nfRegistryApi.postPolicyActionResource(action, resource + '/' + self.nfRegistryService.bucket.identifier, users, groups).subscribe(
+                        function (response) {
+                            // policy created!!!...now update the view
+                            self.nfRegistryApi.getBucket(self.nfRegistryService.bucket.identifier).subscribe(function (response) {
+                                self.nfRegistryService.bucket = response;
+                                var snackBarRef = self.snackBarService.openCoaster({
+                                    title: 'Success',
+                                    message: 'Policy created.',
+                                    verticalPosition: 'bottom',
+                                    horizontalPosition: 'right',
+                                    icon: 'fa fa-check-circle-o',
+                                    color: '#1EB475',
+                                    duration: 3000
+                                });
+                            });
+                        });
+                } else {
+                    // resource exists, let's update it
+                    if (self.userOrGroup.type === 'user') {
+                        policy.users.push(self.userOrGroup);
+                    } else {
+                        policy.userGroups.push(self.userOrGroup);
+                    }
+                    self.nfRegistryApi.putPolicyActionResource(policy.identifier, policy.action,
+                        policy.resource, policy.users, policy.userGroups).subscribe(
+                        function (response) {
+                            // policy updated!!!...now update the view
+                            self.nfRegistryApi.getBucket(self.nfRegistryService.bucket.identifier).subscribe(function (response) {
+                                self.nfRegistryService.bucket = response;
+                                var snackBarRef = self.snackBarService.openCoaster({
+                                    title: 'Success',
+                                    message: 'Policy created.',
+                                    verticalPosition: 'bottom',
+                                    horizontalPosition: 'right',
+                                    icon: 'fa fa-check-circle-o',
+                                    color: '#1EB475',
+                                    duration: 3000
+                                });
+                            });
+                        });
+                }
+            });
+        }
+        if (this.deleteCheckbox.checked) {
+            action = 'delete';
+            permissions.push(action);
+            this.nfRegistryApi.getResourcePoliciesById(action, resource, this.nfRegistryService.bucket.identifier).subscribe(function (policy) {
+                action = 'delete';
+                if (policy.status && policy.status === 404) {
+                    // resource does NOT exist, let's create it
+                    var users = [];
+                    var groups = [];
+
+                    if (self.userOrGroup.type === 'user') {
+                        users.push(self.userOrGroup);
+                    } else {
+                        groups.push(self.userOrGroup);
+                    }
+
+                    self.nfRegistryApi.postPolicyActionResource(action, resource + '/' + self.nfRegistryService.bucket.identifier, users, groups).subscribe(
+                        function (response) {
+                            // policy created!!!...now update the view
+                            self.nfRegistryApi.getBucket(self.nfRegistryService.bucket.identifier).subscribe(function (response) {
+                                self.nfRegistryService.bucket = response;
+                                var snackBarRef = self.snackBarService.openCoaster({
+                                    title: 'Success',
+                                    message: 'Policy created.',
+                                    verticalPosition: 'bottom',
+                                    horizontalPosition: 'right',
+                                    icon: 'fa fa-check-circle-o',
+                                    color: '#1EB475',
+                                    duration: 3000
+                                });
+                            });
+                        });
+                } else {
+                    // resource exists, let's update it
+                    if (self.userOrGroup.type === 'user') {
+                        policy.users.push(self.userOrGroup);
+                    } else {
+                        policy.userGroups.push(self.userOrGroup);
+                    }
+                    self.nfRegistryApi.putPolicyActionResource(policy.identifier, policy.action,
+                        policy.resource, policy.users, policy.userGroups).subscribe(
+                        function (response) {
+                            // policy updated!!!...now update the view
+                            self.nfRegistryApi.getBucket(self.nfRegistryService.bucket.identifier).subscribe(function (response) {
+                                self.nfRegistryService.bucket = response;
+                                var snackBarRef = self.snackBarService.openCoaster({
+                                    title: 'Success',
+                                    message: 'Policy created.',
+                                    verticalPosition: 'bottom',
+                                    horizontalPosition: 'right',
+                                    icon: 'fa fa-check-circle-o',
+                                    color: '#1EB475',
+                                    duration: 3000
+                                });
+                            });
+                        });
+                }
+            });
+        }
+        this.dialogRef.close({userOrGroup: self.userOrGroup, permissions: permissions});
+    },
+
+    /**
+     * Toggle all permission checkboxes.
+     *
+     * @param $event
+     */
+    toggleAllPermissions: function ($event) {
+        if ($event.checked) {
+            this.readCheckbox.checked = true;
+            this.writeCheckbox.checked = true;
+            this.deleteCheckbox.checked = true;
+        } else {
+            this.readCheckbox.checked = false;
+            this.writeCheckbox.checked = false;
+            this.deleteCheckbox.checked = false;
+        }
+    },
+
+    /**
+     * Cancel creation of a new policy and close dialog.
+     */
+    cancel: function () {
+        this.dialogRef.close();
+    }
+};
+
+NfRegistryAddPolicyToBucket.annotations = [
+    new ngCore.Component({
+        template: require('./nf-registry-add-policy-to-bucket.html!text'),
+        queries: {
+            readCheckbox: new ngCore.ViewChild('readCheckbox'),
+            writeCheckbox: new ngCore.ViewChild('writeCheckbox'),
+            deleteCheckbox: new ngCore.ViewChild('deleteCheckbox')
+        }
+    })
+];
+
+NfRegistryAddPolicyToBucket.parameters = [
+    NfRegistryApi,
+    covalentCore.TdDataTableService,
+    fdsSnackBarsModule.FdsSnackBarService,
+    NfRegistryService,
+    ngRouter.ActivatedRoute,
+    ngMaterial.MatDialogRef,
+    ngMaterial.MAT_DIALOG_DATA
+];
+
+module.exports = NfRegistryAddPolicyToBucket;

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/6c48025c/nifi-registry-web-ui/src/main/webapp/components/administration/workflow/dialogs/create-bucket/nf-registry-create-bucket.html
----------------------------------------------------------------------
diff --git a/nifi-registry-web-ui/src/main/webapp/components/administration/workflow/dialogs/create-bucket/nf-registry-create-bucket.html b/nifi-registry-web-ui/src/main/webapp/components/administration/workflow/dialogs/create-bucket/nf-registry-create-bucket.html
new file mode 100644
index 0000000..4248bd2
--- /dev/null
+++ b/nifi-registry-web-ui/src/main/webapp/components/administration/workflow/dialogs/create-bucket/nf-registry-create-bucket.html
@@ -0,0 +1,46 @@
+<!--
+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.
+-->
+
+<div id="nifi-registry-admin-create-bucket-dialog">
+    <div class="pad-bottom-md" fxLayout="row" fxLayoutAlign="space-between center">
+        <span class="md-card-title">New Bucket</span>
+        <button mat-icon-button (click)="cancel()">
+            <mat-icon color="primary">close</mat-icon>
+        </button>
+    </div>
+    <div fxLayout="column" fxLayoutAlign="space-between start" class="pad-bottom-md">
+        <div class="pad-bottom-md fill-available-width">
+            <mat-input-container floatPlaceholder="always" fxFlex>
+                <input #newBucketInput matInput floatPlaceholder="always" placeholder="Bucket Name" focused="true">
+            </mat-input-container>
+        </div>
+        <mat-checkbox [(ngModel)]="keepDialogOpen">
+            Keep this dialog open after creating bucket
+        </mat-checkbox>
+    </div>
+    <div fxLayout="row">
+        <span fxFlex></span>
+        <button (click)="cancel()" color="fds-regular" mat-raised-button
+                i18n="Cancel creation of new bucket|A button for cancelling the creation of a new bucket in the registry.@@nf-admin-workflow-cancel-create-bucket-button">
+            Cancel
+        </button>
+        <button [disabled]="newBucketInput.value.length === 0" class="push-left-sm" (click)="createBucket(newBucketInput)" color="fds-primary" mat-raised-button
+                i18n="Create new bucket button|A button for creating a new bucket in the registry.@@nf-admin-workflow-create-bucket-button">
+            Create
+        </button>
+    </div>
+</div>
\ 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/components/administration/workflow/dialogs/create-bucket/nf-registry-create-bucket.js
----------------------------------------------------------------------
diff --git a/nifi-registry-web-ui/src/main/webapp/components/administration/workflow/dialogs/create-bucket/nf-registry-create-bucket.js b/nifi-registry-web-ui/src/main/webapp/components/administration/workflow/dialogs/create-bucket/nf-registry-create-bucket.js
new file mode 100644
index 0000000..c686ac0
--- /dev/null
+++ b/nifi-registry-web-ui/src/main/webapp/components/administration/workflow/dialogs/create-bucket/nf-registry-create-bucket.js
@@ -0,0 +1,81 @@
+/*
+ * 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.
+ */
+var ngCore = require('@angular/core');
+var NfRegistryService = require('nifi-registry/services/nf-registry.service.js');
+var NfRegistryApi = require('nifi-registry/services/nf-registry.api.js');
+var ngMaterial = require('@angular/material');
+
+/**
+ * NfRegistryCreateBucket constructor.
+ *
+ * @param nfRegistryApi         The api service.
+ * @param nfRegistryService     The nf-registry.service module.
+ * @param matDialogRef          The angular material dialog ref.
+ * @constructor
+ */
+function NfRegistryCreateBucket(nfRegistryApi, nfRegistryService, matDialogRef) {
+    this.nfRegistryService = nfRegistryService;
+    this.nfRegistryApi = nfRegistryApi;
+    this.dialogRef = matDialogRef;
+    this.keepDialogOpen = false;
+};
+
+NfRegistryCreateBucket.prototype = {
+    constructor: NfRegistryCreateBucket,
+
+    /**
+     * Create a new bucket.
+     *
+     * @param newBucketInput     The newBucketInput element.
+     */
+    createBucket: function (newBucketInput) {
+        var self = this;
+        this.nfRegistryApi.createBucket(newBucketInput.value).subscribe(function (bucket) {
+            if (!bucket.error) {
+                self.nfRegistryService.buckets.push(bucket);
+                self.nfRegistryService.filterBuckets();
+                self.nfRegistryService.allBucketsSelected = false;
+                if (self.keepDialogOpen !== true) {
+                    self.dialogRef.close();
+                }
+            } else {
+                self.dialogRef.close();
+            }
+        })
+    },
+
+    /**
+     * Cancel creation of a new bucket and close dialog.
+     */
+    cancel: function () {
+        this.dialogRef.close();
+    }
+};
+
+NfRegistryCreateBucket.annotations = [
+    new ngCore.Component({
+        template: require('./nf-registry-create-bucket.html!text')
+    })
+];
+
+NfRegistryCreateBucket.parameters = [
+    NfRegistryApi,
+    NfRegistryService,
+    ngMaterial.MatDialogRef
+];
+
+module.exports = NfRegistryCreateBucket;

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/6c48025c/nifi-registry-web-ui/src/main/webapp/components/administration/workflow/dialogs/create-bucket/nf-registry-create-bucket.spec.js
----------------------------------------------------------------------
diff --git a/nifi-registry-web-ui/src/main/webapp/components/administration/workflow/dialogs/create-bucket/nf-registry-create-bucket.spec.js b/nifi-registry-web-ui/src/main/webapp/components/administration/workflow/dialogs/create-bucket/nf-registry-create-bucket.spec.js
new file mode 100644
index 0000000..4d4e2f3
--- /dev/null
+++ b/nifi-registry-web-ui/src/main/webapp/components/administration/workflow/dialogs/create-bucket/nf-registry-create-bucket.spec.js
@@ -0,0 +1,77 @@
+/*
+ * 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.
+ */
+
+var NfRegistryApi = require('nifi-registry/services/nf-registry.api.js');
+var NfRegistryService = require('nifi-registry/services/nf-registry.service.js');
+var NfRegistryCreateBucket = require('nifi-registry/components/administration/workflow/dialogs/create-bucket/nf-registry-create-bucket.js');
+var rxjs = require('rxjs/Rx');
+
+describe('NfRegistryCreateBucket Component isolated unit tests', function () {
+    var comp;
+    var nfRegistryService;
+    var nfRegistryApi;
+
+    beforeEach(function () {
+        nfRegistryService = new NfRegistryService();
+        nfRegistryApi = new NfRegistryApi();
+        comp = new NfRegistryCreateBucket(nfRegistryApi, nfRegistryService, {
+            close: function () {
+            }
+        });
+
+        // Spy
+        spyOn(nfRegistryApi, 'createBucket').and.callFake(function () {
+        }).and.returnValue(rxjs.Observable.of({name: 'NewBucket'}));
+        spyOn(nfRegistryService, 'filterBuckets');
+        spyOn(comp.dialogRef, 'close');
+    });
+
+    it('should create a new bucket and close the dialog', function () {
+        // The function to test
+        comp.createBucket({value: 'NewBucket'});
+
+        //assertions
+        expect(comp).toBeDefined();
+        expect(nfRegistryService.buckets.length).toBe(1);
+        expect(nfRegistryService.buckets[0].name).toBe('NewBucket');
+        expect(nfRegistryService.filterBuckets).toHaveBeenCalled();
+        expect(comp.dialogRef.close).toHaveBeenCalled();
+    });
+
+    it('should create a new bucket and keep the dialog open', function () {
+        // setup the component
+        comp.keepDialogOpen = true;
+
+        // The function to test
+        comp.createBucket({value: 'NewBucket'});
+
+        //assertions
+        expect(comp).toBeDefined();
+        expect(nfRegistryService.buckets.length).toBe(1);
+        expect(nfRegistryService.buckets[0].name).toBe('NewBucket');
+        expect(nfRegistryService.filterBuckets).toHaveBeenCalled();
+        expect(comp.dialogRef.close.calls.count()).toEqual(0);
+    });
+
+    it('should close the dialog', function () {
+        // The function to test
+        comp.cancel();
+
+        //assertions
+        expect(comp.dialogRef.close).toHaveBeenCalled();
+    });
+});
\ 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/components/administration/workflow/dialogs/edit-bucket-policy/nf-registry-edit-bucket-policy.html
----------------------------------------------------------------------
diff --git a/nifi-registry-web-ui/src/main/webapp/components/administration/workflow/dialogs/edit-bucket-policy/nf-registry-edit-bucket-policy.html b/nifi-registry-web-ui/src/main/webapp/components/administration/workflow/dialogs/edit-bucket-policy/nf-registry-edit-bucket-policy.html
new file mode 100644
index 0000000..07302d0
--- /dev/null
+++ b/nifi-registry-web-ui/src/main/webapp/components/administration/workflow/dialogs/edit-bucket-policy/nf-registry-edit-bucket-policy.html
@@ -0,0 +1,55 @@
+<!--
+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.
+-->
+
+<div id="nifi-registry-admin-create-bucket-dialog">
+    <div class="pad-bottom-md" fxLayout="row" fxLayoutAlign="space-between center">
+        <span class="md-card-title">Edit Policy</span>
+        <button mat-icon-button (click)="cancel()">
+            <mat-icon color="primary">close</mat-icon>
+        </button>
+    </div>
+    <div flex fxLayoutAlign="start center" class="pad-bottom-md">
+        <mat-input-container flex>
+            <input disabled value="{{userOrGroup.identity}}" #userOrGroupInput matInput placeholder="For This User/Group">
+        </mat-input-container>
+    </div>
+    <div flex fxLayout="row" fxLayoutAlign="start center" class="pad-bottom-md">
+        <mat-checkbox [(checked)]="readCheckbox.checked && writeCheckbox.checked && deleteCheckbox.checked" (change)="toggleAllPermissions($event)">
+            <span class="description">All</span>
+        </mat-checkbox>
+        <mat-checkbox [(checked)]="readCheckbox.checked" #readCheckbox class="pad-left-md">
+            <span class="description">Read</span>
+        </mat-checkbox>
+        <mat-checkbox [(checked)]="writeCheckbox.checked" #writeCheckbox class="pad-left-md">
+            <span class="description">Write</span>
+        </mat-checkbox>
+        <mat-checkbox [(checked)]="deleteCheckbox.checked" #deleteCheckbox class="pad-left-md">
+            <span class="description">Delete</span>
+        </mat-checkbox>
+    </div>
+    <div fxLayout="row">
+        <span fxFlex></span>
+        <button (click)="cancel()" color="fds-regular" mat-raised-button
+                i18n="Cancel creation of new bucket policy|A button for cancelling the creation of a new bucket policy in the registry.@@nf-admin-workflow-cancel-bucket-policy-creation-button">
+            Cancel
+        </button>
+        <button [disabled]="userOrGroupInput.value && !readCheckbox.checked && !writeCheckbox.checked && !deleteCheckbox.checked" class="push-left-sm" (click)="applyPolicy()" color="fds-primary" mat-raised-button
+                i18n="Apply new bucket policy button|A button for applying a new bucket policy in the registry.@@nf-admin-workflow-apply-policy-to-bucket-button">
+            Apply
+        </button>
+    </div>
+</div>
\ No newline at end of file


Mime
View raw message