Repository: nifi-registry
Updated Branches:
  refs/heads/master 870b94787 -> ede45ce60


NIFIREG-31 - Update buckets data table to include search/filter capabilities 
and add bucket creation dialog

This closes #21.

Signed-off-by: Bryan Bende <[email protected]>


Project: http://git-wip-us.apache.org/repos/asf/nifi-registry/repo
Commit: http://git-wip-us.apache.org/repos/asf/nifi-registry/commit/ede45ce6
Tree: http://git-wip-us.apache.org/repos/asf/nifi-registry/tree/ede45ce6
Diff: http://git-wip-us.apache.org/repos/asf/nifi-registry/diff/ede45ce6

Branch: refs/heads/master
Commit: ede45ce607b2f92fff795cf81e274ccc79b9bd3d
Parents: 870b947
Author: Scott Aslan <[email protected]>
Authored: Mon Oct 16 09:39:43 2017 -0400
Committer: Bryan Bende <[email protected]>
Committed: Wed Oct 18 10:38:01 2017 -0400

----------------------------------------------------------------------
 .../src/main/frontend/package.json              |  18 +-
 .../core/common/styles/_helperClasses.scss      |   4 +
 .../platform/core/common/styles/_inputs.scss    |  11 +-
 .../nf-registry-administration.html             |   2 +-
 .../users/nf-registry-users-administration.html |  16 +-
 .../users/nf-registry-users-administration.js   |   1 +
 .../dialogs/nf-registry-create-bucket.html      |  46 +++
 .../dialogs/nf-registry-create-bucket.js        |  69 ++++
 .../dialogs/nf-registry-create-bucket.spec.js   | 110 ++++++
 .../nf-registry-workflow-administration.html    |  57 ++--
 .../nf-registry-workflow-administration.js      |  24 +-
 .../nf-registry-workflow-administration.spec.js |  35 +-
 .../src/main/webapp/nf-registry.html            |   2 -
 .../src/main/webapp/nf-registry.module.js       |  11 +-
 .../main/webapp/services/nf-registry.service.js | 153 +++++++--
 .../webapp/services/nf-registry.service.spec.js | 340 ++++++++++++++++++-
 .../src/main/webapp/systemjs.builder.config.js  |   1 +
 .../general/_structureElements.scss             |  25 --
 .../users/_structureElements.scss               |   4 +-
 .../workflow/_structureElements.scss            |  30 +-
 .../src/main/webapp/theming/nf-registry.scss    |   1 -
 21 files changed, 794 insertions(+), 166 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/ede45ce6/nifi-registry-web-ui/src/main/frontend/package.json
----------------------------------------------------------------------
diff --git a/nifi-registry-web-ui/src/main/frontend/package.json 
b/nifi-registry-web-ui/src/main/frontend/package.json
index c7615bd..b529e09 100644
--- a/nifi-registry-web-ui/src/main/frontend/package.json
+++ b/nifi-registry-web-ui/src/main/frontend/package.json
@@ -21,18 +21,18 @@
     "roboto-fontface": "0.7.0"
   },
   "devDependencies": {
-    "@angular/animations": "4.2.0",
+    "@angular/animations": "4.3.4",
     "@angular/cdk": "2.0.0-beta.8",
-    "@angular/common": "4.2.0",
-    "@angular/compiler": "4.2.0",
-    "@angular/core": "4.2.0",
+    "@angular/common": "4.3.4",
+    "@angular/compiler": "4.3.4",
+    "@angular/core": "4.3.4",
     "@angular/flex-layout": "2.0.0-beta.8",
-    "@angular/forms": "4.2.0",
-    "@angular/http": "4.2.0",
+    "@angular/forms": "4.3.4",
+    "@angular/http": "4.3.4",
     "@angular/material": "2.0.0-beta.6",
-    "@angular/platform-browser": "4.2.0",
-    "@angular/platform-browser-dynamic": "4.2.0",
-    "@angular/router": "4.2.0",
+    "@angular/platform-browser": "4.3.4",
+    "@angular/platform-browser-dynamic": "4.3.4",
+    "@angular/router": "4.3.4",
     "canonical-path": "0.0.2",
     "grunt": "0.4.5",
     "grunt-cli": "1.2.0",

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/ede45ce6/nifi-registry-web-ui/src/main/platform/core/common/styles/_helperClasses.scss
----------------------------------------------------------------------
diff --git 
a/nifi-registry-web-ui/src/main/platform/core/common/styles/_helperClasses.scss 
b/nifi-registry-web-ui/src/main/platform/core/common/styles/_helperClasses.scss
index 6ae237c..c878c15 100644
--- 
a/nifi-registry-web-ui/src/main/platform/core/common/styles/_helperClasses.scss
+++ 
b/nifi-registry-web-ui/src/main/platform/core/common/styles/_helperClasses.scss
@@ -70,3 +70,7 @@
   margin-left: auto;
   margin-right: auto;
 }
+
+.fill-available-width {
+  width: 100%;
+}

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/ede45ce6/nifi-registry-web-ui/src/main/platform/core/common/styles/_inputs.scss
----------------------------------------------------------------------
diff --git 
a/nifi-registry-web-ui/src/main/platform/core/common/styles/_inputs.scss 
b/nifi-registry-web-ui/src/main/platform/core/common/styles/_inputs.scss
index 7024363..31cf0d4 100644
--- a/nifi-registry-web-ui/src/main/platform/core/common/styles/_inputs.scss
+++ b/nifi-registry-web-ui/src/main/platform/core/common/styles/_inputs.scss
@@ -87,9 +87,9 @@ body[fds] .mat-input-placeholder.mat-float:not(.mat-empty) {
 }
 
 body[fds] .input-button {
-  top: 3.5px;
-  left: -24px;
-  z-index: 1;
+  top: 3px;
+  left: -4px;
+  border-left: none !important;
 }
 
 body[fds] .input-button.mat-raised-button[disabled] {
@@ -97,8 +97,7 @@ body[fds] .input-button.mat-raised-button[disabled] {
 }
 
 body[fds] .mat-input-infix {
-  padding: 7px 23px 0px 0px;
-  border-top: 0;
+  padding: 7px 3px 0px 0px;
 }
 
 body[fds] td-chips .mat-input-placeholder-wrapper::after {
@@ -115,7 +114,7 @@ body[fds] td-chips input.mat-input-element {
   color: $grey2;
   border: 1px solid $grey8;
   height: 32px;
-  padding: 0px 10px;
+  padding: 0px 6px 0px 0px;
   width: 100%;
 }
 

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/ede45ce6/nifi-registry-web-ui/src/main/webapp/components/administration/nf-registry-administration.html
----------------------------------------------------------------------
diff --git 
a/nifi-registry-web-ui/src/main/webapp/components/administration/nf-registry-administration.html
 
b/nifi-registry-web-ui/src/main/webapp/components/administration/nf-registry-administration.html
index b9b9909..edafcaf 100644
--- 
a/nifi-registry-web-ui/src/main/webapp/components/administration/nf-registry-administration.html
+++ 
b/nifi-registry-web-ui/src/main/webapp/components/administration/nf-registry-administration.html
@@ -27,7 +27,7 @@ limitations under the License.
                           class="uppercase"
                           routerLink="/nifi-registry/administration/workflow"
                           i18n="Workflow administration tab|A description of 
the type of administration options available.@@nf-admin-workflow-tab-title">
-            Workflow
+            Buckets
         </md-button-toggle>
     </md-button-toggle-group>
 </div>

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/ede45ce6/nifi-registry-web-ui/src/main/webapp/components/administration/users/nf-registry-users-administration.html
----------------------------------------------------------------------
diff --git 
a/nifi-registry-web-ui/src/main/webapp/components/administration/users/nf-registry-users-administration.html
 
b/nifi-registry-web-ui/src/main/webapp/components/administration/users/nf-registry-users-administration.html
index 4dd9055..5516901 100644
--- 
a/nifi-registry-web-ui/src/main/webapp/components/administration/users/nf-registry-users-administration.html
+++ 
b/nifi-registry-web-ui/src/main/webapp/components/administration/users/nf-registry-users-administration.html
@@ -16,10 +16,10 @@ limitations under the License.
 -->
 
 <div id="nifi-registry-users-administration-perspective" 
class="mat-elevation-z5">
-    <div layout="row" layout-align="space-between top" class="pad-top-md 
pad-bottom-sm pad-left-md pad-right-md">
-        <span class="mat-card-title">Authorized Users 
({{usersPagingBar.range}}) <span hide-xs>of 
{{usersPagingBar.total}}</span></span>
+    <div fxFlex class="pad-top-md pad-bottom-sm pad-left-md pad-right-md">
+        <span class="mat-card-title">Authorized Users 
({{nfRegistryService.users.length}})</span>
         <div flex class="push-right-sm" fxLayout="row" fxLayoutAlign="end 
center">
-            <td-chips [items]="nfRegistryService.autoCompleteUsers" 
(add)="nfRegistryService.usersSearchAdd($event)"
+            <td-chips class="push-right-sm" 
[items]="nfRegistryService.autoCompleteUsers" 
(add)="nfRegistryService.usersSearchAdd($event)"
                       
(remove)="nfRegistryService.usersSearchRemove($event)"></td-chips>
             <button class="push-right-sm" color="fds-secondary" 
md-raised-button (click)="execute({name: 'add'})">
                 Add User
@@ -33,12 +33,10 @@ limitations under the License.
                 users
             </button>
         </md-menu>
-    </div>
-    <div class="pad-left-md pad-right-md">
         <div 
id="nifi-registry-users-administration-list-container-column-header" 
fxLayout="row"
              fxLayoutAlign="space-between center" class="td-data-table">
             <div class="td-data-table-column" 
(click)="nfRegistryService.sortUsers($event, column)"
-                 [mdTooltip]="column.tooltip" *ngFor="let column of 
nfRegistryService.userColumns"
+                 *ngFor="let column of nfRegistryService.userColumns"
                  fxFlex="{{column.width}}">
                 {{column.label}}
                 <i *ngIf="column.active && column.sortable && column.sortOrder 
=== 'ASC'" class="fa fa-caret-up"
@@ -111,12 +109,6 @@ limitations under the License.
              layout-align="center center">
             <h3>No results to display.</h3>
         </div>
-        <td-paging-bar id="nifi-registry-users-administration-list-paging-bar" 
#usersPagingBar [pageSizeAll]="true"
-                       [pageSizes]="[1, 2, 50, 100, 200, 500, 1000, 2000]"
-                       [initialPage]="1" 
[pageSize]="nfRegistryService.usersPageSize"
-                       [total]="nfRegistryService.usersPageCount" 
(change)="nfRegistryService.pageUsers($event)">
-            <span td-paging-bar-label hide-xs>Row per page:</span>
-        </td-paging-bar>
     </div>
 </div>
 <router-outlet></router-outlet>

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/ede45ce6/nifi-registry-web-ui/src/main/webapp/components/administration/users/nf-registry-users-administration.js
----------------------------------------------------------------------
diff --git 
a/nifi-registry-web-ui/src/main/webapp/components/administration/users/nf-registry-users-administration.js
 
b/nifi-registry-web-ui/src/main/webapp/components/administration/users/nf-registry-users-administration.js
index f5405ba..32cf758 100644
--- 
a/nifi-registry-web-ui/src/main/webapp/components/administration/users/nf-registry-users-administration.js
+++ 
b/nifi-registry-web-ui/src/main/webapp/components/administration/users/nf-registry-users-administration.js
@@ -61,6 +61,7 @@ NfRegistryUsersAdministration.prototype = {
     ngOnDestroy: function () {
         this.nfRegistryService.adminPerspective = '';
         this.nfRegistryService.users = this.nfRegistryService.filteredUsers = 
[];
+        this.nfRegistryService.allUsersSelected = false;
     },
 
     /**

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/ede45ce6/nifi-registry-web-ui/src/main/webapp/components/administration/workflow/dialogs/nf-registry-create-bucket.html
----------------------------------------------------------------------
diff --git 
a/nifi-registry-web-ui/src/main/webapp/components/administration/workflow/dialogs/nf-registry-create-bucket.html
 
b/nifi-registry-web-ui/src/main/webapp/components/administration/workflow/dialogs/nf-registry-create-bucket.html
new file mode 100644
index 0000000..02cfbc7
--- /dev/null
+++ 
b/nifi-registry-web-ui/src/main/webapp/components/administration/workflow/dialogs/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="mat-card-title">New Bucket</span>
+        <button md-icon-button (click)="cancel()">
+            <md-icon color="primary">close</md-icon>
+        </button>
+    </div>
+    <div fxLayout="column" fxLayoutAlign="space-between start" 
class="pad-bottom-md">
+        <div class="pad-bottom-md fill-available-width">
+            <md-input-container floatPlaceholder="always" fxFlex>
+                <input #newBucketInput mdInput floatPlaceholder="always" 
placeholder="Bucket Name">
+            </md-input-container>
+        </div>
+        <md-checkbox [(ngModel)]="keepDialogOpen">
+            Keep this dialog open after creating bucket
+        </md-checkbox>
+    </div>
+    <div fxLayout="row">
+        <span fxFlex></span>
+        <button (click)="cancel()" color="fds-regular" md-raised-button
+                i18n="Cancel creation of new bucket|A button for cancelling 
the creation of a new bucket in the 
registry.@@nf-admin-workflow-create-bucket-button">
+            Cancel
+        </button>
+        <button [disabled]="newBucketInput.value.length === 0" 
class="push-left-sm" (click)="createBucket(newBucketInput)" color="fds-primary" 
md-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/ede45ce6/nifi-registry-web-ui/src/main/webapp/components/administration/workflow/dialogs/nf-registry-create-bucket.js
----------------------------------------------------------------------
diff --git 
a/nifi-registry-web-ui/src/main/webapp/components/administration/workflow/dialogs/nf-registry-create-bucket.js
 
b/nifi-registry-web-ui/src/main/webapp/components/administration/workflow/dialogs/nf-registry-create-bucket.js
new file mode 100644
index 0000000..236fd72
--- /dev/null
+++ 
b/nifi-registry-web-ui/src/main/webapp/components/administration/workflow/dialogs/nf-registry-create-bucket.js
@@ -0,0 +1,69 @@
+/*
+ * 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 ngMaterial = require('@angular/material');
+
+/**
+ * NfRegistryCreateBucket constructor.
+ *
+ * @param nfRegistryService     The nf-registry.service module.
+ * @param matDialogRef          The angular material dialog ref.
+ * @constructor
+ */
+function NfRegistryCreateBucket(nfRegistryService, matDialogRef) {
+    this.nfRegistryService = nfRegistryService;
+    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.nfRegistryService.api.createBucket(newBucketInput.value).subscribe(function
 (bucket) {
+            self.nfRegistryService.buckets.push(bucket);
+            self.nfRegistryService.filterBuckets();
+            if (self.keepDialogOpen !== true) {
+                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 = [NfRegistryService, 
ngMaterial.MdDialogRef];
+
+module.exports = NfRegistryCreateBucket;

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/ede45ce6/nifi-registry-web-ui/src/main/webapp/components/administration/workflow/dialogs/nf-registry-create-bucket.spec.js
----------------------------------------------------------------------
diff --git 
a/nifi-registry-web-ui/src/main/webapp/components/administration/workflow/dialogs/nf-registry-create-bucket.spec.js
 
b/nifi-registry-web-ui/src/main/webapp/components/administration/workflow/dialogs/nf-registry-create-bucket.spec.js
new file mode 100644
index 0000000..bada058
--- /dev/null
+++ 
b/nifi-registry-web-ui/src/main/webapp/components/administration/workflow/dialogs/nf-registry-create-bucket.spec.js
@@ -0,0 +1,110 @@
+/*
+ * 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 NfRegistryRoutes = require('nifi-registry/nf-registry.routes.js');
+var ngCoreTesting = require('@angular/core/testing');
+var ngCommon = require('@angular/common');
+var ngRouter = require('@angular/router');
+var ngPlatformBrowser = require('@angular/platform-browser');
+var FdsDemo = 
require('nifi-registry/components/fluid-design-system/fds-demo.js');
+var NfRegistry = require('nifi-registry/nf-registry.js');
+var NfRegistryApi = require('nifi-registry/services/nf-registry.api.js');
+var NfRegistryService = 
require('nifi-registry/services/nf-registry.service.js');
+var NfPageNotFoundComponent = 
require('nifi-registry/components/page-not-found/nf-registry-page-not-found.js');
+var NfRegistryExplorer = 
require('nifi-registry/components/explorer/nf-registry-explorer.js');
+var NfRegistryAdministration = 
require('nifi-registry/components/administration/nf-registry-administration.js');
+var NfRegistryUsersAdministration = 
require('nifi-registry/components/administration/users/nf-registry-users-administration.js');
+var NfRegistryAddUser = 
require('nifi-registry/components/administration/users/add/nf-registry-add-user.js');
+var NfRegistryUserDetails = 
require('nifi-registry/components/administration/users/details/nf-registry-user-details.js');
+var NfRegistryUserPermissions = 
require('nifi-registry/components/administration/users/permissions/nf-registry-user-permissions.js');
+var NfRegistryBucketPermissions = 
require('nifi-registry/components/administration/workflow/buckets/permissions/nf-registry-bucket-permissions.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 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');
+var fdsCore = require('@fluid-design-system/core');
+var ngMoment = require('angular2-moment');
+var rxjs = require('rxjs/Rx');
+var ngHttp = require('@angular/http');
+
+describe('NfRegistryCreateBucket Component', function () {
+    var comp;
+    var fixture;
+    var de;
+    var el;
+    var nfRegistryService;
+
+    beforeEach(function () {
+        nfRegistryService = new NfRegistryService({}, {
+            createBucket: function() {}
+        }, {}, {});
+        comp = new NfRegistryCreateBucket(nfRegistryService, {
+            close: function() {}
+        })
+    });
+
+    it('should create a new bucket and close the dialog', function () {
+        // Spy
+        spyOn(nfRegistryService.api, 'createBucket').and.callFake(function () {
+        }).and.returnValue(rxjs.Observable.of({name: 'NewBucket'}));
+        spyOn(nfRegistryService, 'filterBuckets');
+        spyOn(comp.dialogRef, 'close');
+
+        // 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 () {
+        // Spy
+        spyOn(nfRegistryService.api, 'createBucket').and.callFake(function () {
+        }).and.returnValue(rxjs.Observable.of({name: 'NewBucket'}));
+        spyOn(nfRegistryService, 'filterBuckets');
+        spyOn(comp.dialogRef, 'close');
+
+        // 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 () {
+        // Spy
+        spyOn(comp.dialogRef, 'close');
+
+        // 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/ede45ce6/nifi-registry-web-ui/src/main/webapp/components/administration/workflow/nf-registry-workflow-administration.html
----------------------------------------------------------------------
diff --git 
a/nifi-registry-web-ui/src/main/webapp/components/administration/workflow/nf-registry-workflow-administration.html
 
b/nifi-registry-web-ui/src/main/webapp/components/administration/workflow/nf-registry-workflow-administration.html
index ebf689d..16f618f 100644
--- 
a/nifi-registry-web-ui/src/main/webapp/components/administration/workflow/nf-registry-workflow-administration.html
+++ 
b/nifi-registry-web-ui/src/main/webapp/components/administration/workflow/nf-registry-workflow-administration.html
@@ -18,19 +18,26 @@ limitations under the License.
 <div id="nifi-registry-workflow-administration-perspective-buckets-container" 
class="mat-elevation-z5">
     <div fxFlex class="pad-top-md pad-bottom-sm pad-left-md pad-right-md">
         <span class="mat-card-title">Buckets 
({{nfRegistryService.buckets.length}})</span>
-        <div flex fxLayoutAlign="start center" class="pad-top-md 
pad-bottom-sm">
-            <md-input-container flex>
-                <input #newBucketInput mdInput placeholder="Create New Bucket">
-            </md-input-container>
-            <button (click)="createBucket(newBucketInput)" 
class="input-button" color="fds-regular" md-raised-button
-                    i18n="Create new bucket button|A button for creating a new 
bucket in the registry.@@nf-admin-workflow-create-bucket-button">
-                Create
+        <div flex class="push-right-sm" fxLayout="row" fxLayoutAlign="end 
center">
+            <td-chips class="push-right-sm" 
[items]="nfRegistryService.autoCompleteBuckets" 
(add)="nfRegistryService.bucketsSearchAdd($event)"
+                      
(remove)="nfRegistryService.bucketsSearchRemove($event)"></td-chips>
+            <button class="push-right-sm" color="fds-secondary" 
md-raised-button (click)="createBucket()">
+                New Bucket
+            </button>
+            <button [disabled]="nfRegistryService.disableMultiBucketActions" 
color="fds-primary" md-raised-button [mdMenuTriggerFor]="bucketActionMenu">
+                Actions<i class="fa fa-caret-down" aria-hidden="true"></i>
             </button>
         </div>
+        <md-menu class="fds-primary-dropdown-button-menu" 
#bucketActionMenu="mdMenu" [overlapTrigger]="false">
+            <button md-menu-item
+                    (click)="nfRegistryService.deleteSelectedBuckets()">
+                <span>Delete</span>
+            </button>
+        </md-menu>
         <div 
id="nifi-registry-workflow-administration-buckets-list-container-column-header" 
fxLayout="row"
              fxLayoutAlign="space-between center" class="td-data-table">
-            <div class="td-data-table-column" 
(click)="nfRegistryService.sortBuckets($event, column)"
-                 [mdTooltip]="column.tooltip" *ngFor="let column of 
nfRegistryService.bucketColumns"
+            <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"
@@ -38,12 +45,18 @@ limitations under the License.
                 <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 class="td-data-table-column">
+                <div fxLayout="row" fxLayoutAlign="end center">
+                    <md-checkbox class="pad-left-sm" 
[(ngModel)]="nfRegistryService.allBucketsSelected"
+                                 
(checked)="nfRegistryService.allBucketsSelected"
+                                 
(change)="nfRegistryService.toggleBucketsSelectAll()"></md-checkbox>
+                </div>
+            </div>
         </div>
         <div id="nifi-registry-workflow-administration-buckets-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.toggleBucketSelect(row)">
+                 (click)="row.checked = 
!row.checked;nfRegistryService.determineAllBucketsSelectedState()">
                 <div class="td-data-table-cell" *ngFor="let column of 
nfRegistryService.bucketColumns"
                      fxFlex="{{column.width}}">
                     <div>
@@ -53,14 +66,15 @@ limitations under the License.
                 <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"
+                            <button 
(click)="nfRegistryService.executeBucketAction(action, row);row.checked = 
!row.checked;"
+                                    *ngFor="let action of bucketActions"
                                     mdTooltip="{{action.tooltip}}" 
md-icon-button color="accent"
                                     [disabled]="action.disabled ? '' : null">
                                 <i class="{{action.icon}}" 
aria-hidden="true"></i>
                             </button>
                             <md-checkbox class="pad-left-sm" 
[(ngModel)]="row.checked" [checked]="row.checked"
-                                         
(change)="nfRegistryService.toggleBucketSelect(row)"
-                                         (click)="row.checked = 
!row.checked;nfRegistryService.toggleBucketSelect(row)"></md-checkbox>
+                                         
(change)="nfRegistryService.determineAllBucketsSelectedState()"
+                                         (click)="row.checked = 
!row.checked;nfRegistryService.determineAllBucketsSelectedState()"></md-checkbox>
                         </div>
                         <div *ngIf="bucketActions.length > 4" fxLayout="row" 
fxLayoutAlign="end center">
                             <button (click)="row.checked = !row.checked" 
mdTooltip="Actions" md-icon-button
@@ -68,7 +82,8 @@ limitations under the License.
                                 <i class="fa fa-ellipsis-h" 
aria-hidden="true"></i>
                             </button>
                             <md-menu #bucketTableActionMenu="mdMenu" 
[overlapTrigger]="false">
-                                <button 
(click)="nfRegistryService.executeBucketAction(action, row);row.checked = 
!row.checked;" *ngFor="let action of bucketActions"
+                                <button 
(click)="nfRegistryService.executeBucketAction(action, row);row.checked = 
!row.checked;"
+                                        *ngFor="let action of bucketActions"
                                         mdTooltip="{{action.tooltip}}" 
md-menu-item
                                         [disabled]="action.disabled ? '' : 
null">
                                     <i class="{{action.icon}}" 
aria-hidden="true"></i>
@@ -76,18 +91,22 @@ limitations under the License.
                                 </button>
                             </md-menu>
                             <md-checkbox [(ngModel)]="row.checked" 
[checked]="row.checked"
-                                         
(change)="nfRegistryService.toggleBucketSelect(row)"
-                                         (click)="row.checked = 
!row.checked;nfRegistryService.toggleBucketSelect(row)"></md-checkbox>
+                                         
(change)="nfRegistryService.determineAllBucketsSelectedState()"
+                                         (click)="row.checked = 
!row.checked;nfRegistryService.determineAllBucketsSelectedState()"></md-checkbox>
                         </div>
                     </div>
                     <div *ngIf="!bucketActions" fxLayout="row" 
fxLayoutAlign="end center">
                         <md-checkbox [(ngModel)]="row.checked" 
[checked]="row.checked"
-                                     
(change)="nfRegistryService.toggleBucketSelect(row)"
-                                     (click)="row.checked = 
!row.checked;nfRegistryService.toggleBucketSelect(row)"></md-checkbox>
+                                     
(change)="nfRegistryService.determineAllBucketsSelectedState(row)"
+                                     (click)="row.checked = 
!row.checked;nfRegistryService.determineAllBucketsSelectedState()"></md-checkbox>
                     </div>
                 </div>
             </div>
         </div>
+        <div class="md-padding" 
*ngIf="!nfRegistryService.filteredBuckets.length > 0" layout="row"
+             layout-align="center center">
+            <h3>No results to display.</h3>
+        </div>
     </div>
 </div>
 <router-outlet></router-outlet>

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/ede45ce6/nifi-registry-web-ui/src/main/webapp/components/administration/workflow/nf-registry-workflow-administration.js
----------------------------------------------------------------------
diff --git 
a/nifi-registry-web-ui/src/main/webapp/components/administration/workflow/nf-registry-workflow-administration.js
 
b/nifi-registry-web-ui/src/main/webapp/components/administration/workflow/nf-registry-workflow-administration.js
index 1101a84..3327dc2 100644
--- 
a/nifi-registry-web-ui/src/main/webapp/components/administration/workflow/nf-registry-workflow-administration.js
+++ 
b/nifi-registry-web-ui/src/main/webapp/components/administration/workflow/nf-registry-workflow-administration.js
@@ -16,22 +16,26 @@
  */
 var ngCore = require('@angular/core');
 var NfRegistryService = 
require('nifi-registry/services/nf-registry.service.js');
+var NfRegistryCreateBucket = 
require('nifi-registry/components/administration/workflow/dialogs/nf-registry-create-bucket.js');
 var nfRegistryAnimations = require('nifi-registry/nf-registry.animations.js');
 var ngRouter = require('@angular/router');
+var ngMaterial = require('@angular/material');
 
 /**
  * NfRegistryWorkflowAdministration constructor.
  *
  * @param nfRegistryService     The nf-registry.service module.
  * @param ActivatedRoute        The angular activated route module.
+ * @param matDialogRef          The angular material dialog ref.
  * @constructor
  */
-function NfRegistryWorkflowAdministration(nfRegistryService, ActivatedRoute) {
+function NfRegistryWorkflowAdministration(nfRegistryService, ActivatedRoute, 
matDialog) {
     this.route = ActivatedRoute;
     this.nfRegistryService = nfRegistryService;
+    this.dialog = matDialog;
     this.bucketActions = [{
         'name': 'permissions',
-        'icon': 'fa fa-key',
+        'icon': 'fa fa-pencil',
         'tooltip': 'Manage Bucket Policies',
         'type': 'sidenav'
     }, {
@@ -66,19 +70,15 @@ NfRegistryWorkflowAdministration.prototype = {
      */
     ngOnDestroy: function () {
         this.nfRegistryService.adminPerspective = '';
-        this.nfRegistryService.buckets = [];
-        this.nfRegistryService.filteredBuckets = [];
+        this.nfRegistryService.buckets = 
this.nfRegistryService.filteredBuckets = [];
+        this.nfRegistryService.allBucketsSelected = false;
     },
 
     /**
-     * Create a new bucket.
+     * Opens the create new bucket dialog.
      */
-    createBucket: function (newBucketInput) {
-        var self = this;
-        
this.nfRegistryService.api.createBucket(newBucketInput.value).subscribe(function
 (bucket) {
-            self.nfRegistryService.buckets.push(bucket);
-            self.nfRegistryService.filterBuckets();
-        })
+    createBucket: function () {
+        this.dialog.open(NfRegistryCreateBucket);
     }
 };
 
@@ -92,6 +92,6 @@ NfRegistryWorkflowAdministration.annotations = [
     })
 ];
 
-NfRegistryWorkflowAdministration.parameters = [NfRegistryService, 
ngRouter.ActivatedRoute];
+NfRegistryWorkflowAdministration.parameters = [NfRegistryService, 
ngRouter.ActivatedRoute, ngMaterial.MdDialog];
 
 module.exports = NfRegistryWorkflowAdministration;

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/ede45ce6/nifi-registry-web-ui/src/main/webapp/components/administration/workflow/nf-registry-workflow-administration.spec.js
----------------------------------------------------------------------
diff --git 
a/nifi-registry-web-ui/src/main/webapp/components/administration/workflow/nf-registry-workflow-administration.spec.js
 
b/nifi-registry-web-ui/src/main/webapp/components/administration/workflow/nf-registry-workflow-administration.spec.js
index 5d16c66..7508530 100644
--- 
a/nifi-registry-web-ui/src/main/webapp/components/administration/workflow/nf-registry-workflow-administration.spec.js
+++ 
b/nifi-registry-web-ui/src/main/webapp/components/administration/workflow/nf-registry-workflow-administration.spec.js
@@ -33,6 +33,7 @@ var NfRegistryUserDetails = 
require('nifi-registry/components/administration/use
 var NfRegistryUserPermissions = 
require('nifi-registry/components/administration/users/permissions/nf-registry-user-permissions.js');
 var NfRegistryBucketPermissions = 
require('nifi-registry/components/administration/workflow/buckets/permissions/nf-registry-bucket-permissions.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 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');
@@ -69,11 +70,15 @@ describe('NfRegistryWorkflowAdministration Component', 
function () {
                 NfRegistryBucketPermissions,
                 NfRegistryAddUser,
                 NfRegistryWorkflowAdministration,
+                NfRegistryCreateBucket,
                 NfRegistryGridListViewer,
                 NfRegistryBucketGridListViewer,
                 NfRegistryDropletGridListViewer,
                 NfPageNotFoundComponent
             ],
+            entryComponents: [
+                NfRegistryCreateBucket
+            ],
             providers: [
                 NfRegistryService,
                 NfRegistryApi,
@@ -88,9 +93,9 @@ describe('NfRegistryWorkflowAdministration Component', 
function () {
                 }
             ]
         });
-        
+
         fixture = 
ngCoreTesting.TestBed.createComponent(NfRegistryWorkflowAdministration);
-        
+
         // test instance
         comp = fixture.componentInstance;
 
@@ -99,7 +104,7 @@ describe('NfRegistryWorkflowAdministration Component', 
function () {
         nfRegistryApi = ngCoreTesting.TestBed.get(NfRegistryApi);
         de = 
fixture.debugElement.query(ngPlatformBrowser.By.css('#nifi-registry-workflow-administration-perspective-buckets-container'));
         el = de.nativeElement;
-        
+
         // Spy
         spyOn(nfRegistryService.api, 'getDroplets').and.callFake(function () {
         }).and.returnValue(rxjs.Observable.of([{
@@ -140,23 +145,16 @@ describe('NfRegistryWorkflowAdministration Component', 
function () {
         });
     }));
 
-    it('should create a new bucket', ngCoreTesting.async(function () {
+    it('should open a dialog to create a new bucket', function () {
+        spyOn(comp.dialog, 'open')
         fixture.detectChanges();
-        fixture.whenStable().then(function () { // wait for async getBuckets
-            fixture.detectChanges();
-            comp.createBucket({value: 'This bucket name.'});
-            fixture.detectChanges();
-            fixture.whenStable().then(function () { // wait for async 
createBucket
-                fixture.detectChanges();
 
-                //assertions
-                expect(nfRegistryApi.createBucket).toHaveBeenCalledWith('This 
bucket name.');
-                expect(nfRegistryService.buckets[1].name).toEqual('Newly 
Created Bucket');
-                expect(nfRegistryService.buckets.length).toBe(2);
-                expect(nfRegistryService.filterBuckets).toHaveBeenCalled();
-            });
-        });
-    }));
+        // the function to test
+        comp.createBucket();
+
+        //assertions
+        expect(comp.dialog.open).toBeDefined();
+    });
 
     it('should destroy the component', ngCoreTesting.fakeAsync(function () {
         fixture.detectChanges();
@@ -171,5 +169,6 @@ describe('NfRegistryWorkflowAdministration Component', 
function () {
         expect(nfRegistryService.adminPerspective).toBe('');
         expect(nfRegistryService.buckets.length).toBe(0);
         expect(nfRegistryService.filteredBuckets.length).toBe(0);
+        expect(nfRegistryService.allBucketsSelected).toBe(false);
     }));
 });
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/ede45ce6/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 ae83d6e..b6c4e48 100644
--- a/nifi-registry-web-ui/src/main/webapp/nf-registry.html
+++ b/nifi-registry-web-ui/src/main/webapp/nf-registry.html
@@ -71,12 +71,10 @@ limitations under the License.
                 <i class="fa fa-bell" aria-hidden="true"></i>
             </button>
             <button md-ripple [@flyInOut] *ngIf="nfRegistryService.perspective 
=== 'explorer'" md-icon-button
-                    mdTooltip="Registry Administration"
                     routerLink="/nifi-registry/administration/users">
                 <i class="fa fa-wrench" aria-hidden="true"></i>
             </button>
             <button md-ripple [@flyInOut] *ngIf="nfRegistryService.perspective 
=== 'administration'" md-mini-fab
-                    mdTooltip="Close settings and return to Explorer 
perspective."
                     
routerLink="/nifi-registry/explorer/{{(nfRegistryService.explorerViewType) ? 
nfRegistryService.explorerViewType : 'grid-list'}}">
                 <md-icon color="primary">close</md-icon>
             </button>

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/ede45ce6/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 c70ca6d..a44f7b8 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
@@ -31,6 +31,7 @@ var NfRegistryUserDetails = 
require('nifi-registry/components/administration/use
 var NfRegistryUserPermissions = 
require('nifi-registry/components/administration/users/permissions/nf-registry-user-permissions.js');
 var NfRegistryBucketPermissions = 
require('nifi-registry/components/administration/workflow/buckets/permissions/nf-registry-bucket-permissions.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 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');
@@ -64,13 +65,19 @@ NfRegistryModule.annotations = [
             NfRegistryBucketPermissions,
             NfRegistryAddUser,
             NfRegistryWorkflowAdministration,
+            NfRegistryCreateBucket,
             NfRegistryGridListViewer,
             NfRegistryBucketGridListViewer,
             NfRegistryDropletGridListViewer,
-            NfPageNotFoundComponent],
+            NfPageNotFoundComponent
+        ],
+        entryComponents: [
+            NfRegistryCreateBucket
+        ],
         providers: [
             NfRegistryService,
-            NfRegistryApi],
+            NfRegistryApi
+        ],
         bootstrap: [NfRegistry]
     })
 ];

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/ede45ce6/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 308db56..2fcb1fe 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
@@ -75,42 +75,33 @@ function NfRegistryService(TdDataTableService, 
NfRegistryApi, Router, FdsDialogS
     this.dataTableService = TdDataTableService;
 
     this.filteredDroplets = [];
-
     this.dropletColumns = [
         {name: 'name', label: 'Name', sortable: true},
         {name: 'updated', label: 'Updated', sortable: true}
     ];
-
     this.autoCompleteDroplets = [];
     this.dropletsSearchTerms = [];
 
     this.filteredBuckets = [];
-
     this.bucketColumns = [
         {name: 'name', label: 'Bucket Name', sortable: true, tooltip: 'Sort 
Buckets by name.'}
     ];
-
     this.allBucketsSelected = false;
     this.autoCompleteBuckets = [];
+    this.selectedBuckets = [];
     this.bucketsSearchTerms = [];
+    this.disableMultiBucketActions = true;
 
     this.filteredUsers = [];
-
     this.userColumns = [
         {name: 'status', label: 'Status', sortable: true, tooltip: 'User 
Status.', width: 18},
         {name: 'name', label: 'Name', sortable: true, tooltip: 'User name.', 
width: 30},
         {name: 'provider', label: 'Provider', sortable: true, tooltip: 
'Authentication provider.', width: 30}
     ];
-
     this.allUsersSelected = false;
     this.autoCompleteUsers = [];
     this.selectedUsers = [];
-
     this.usersSearchTerms = [];
-    this.usersFromRow = 1;
-    this.usersCurrentPage = 1;
-    this.usersPageSize = 5;
-    this.usersPageCount = 0;
 };
 
 NfRegistryService.prototype = {
@@ -191,8 +182,8 @@ NfRegistryService.prototype = {
             }).afterClosed().subscribe(
                 function (accept) {
                     if (accept) {
-                        
self.api.deleteDroplet(droplet.link.href).subscribe(function(){
-                            self.droplets = self.droplets.filter(function(d){
+                        
self.api.deleteDroplet(droplet.link.href).subscribe(function () {
+                            self.droplets = self.droplets.filter(function (d) {
                                 return (d.identifier !== droplet.identifier) ? 
true : false
                             });
                             self.filterDroplets();
@@ -208,7 +199,7 @@ NfRegistryService.prototype = {
      * @param droplet       The droplet.
      */
     getDropletSnapshotMetadata: function (droplet) {
-        this.api.getDropletSnapshotMetadata(droplet.link.href, 
true).subscribe(function(snapshotMetadata) {
+        this.api.getDropletSnapshotMetadata(droplet.link.href, 
true).subscribe(function (snapshotMetadata) {
             droplet.snapshotMetadata = snapshotMetadata;
         })
     },
@@ -369,6 +360,16 @@ NfRegistryService.prototype = {
 
         newData = this.dataTableService.sortData(newData, sortBy, sortOrder);
         this.filteredBuckets = newData;
+
+        var selected = 0;
+        this.filteredBuckets.forEach(function (filteredBucket) {
+            if (filteredBucket.checked) {
+                selected++;
+            }
+        });
+
+        this.disableMultiBucketActions = (selected > 0) ? false : true;
+
         this.getAutoCompleteBuckets();
     },
 
@@ -390,7 +391,7 @@ NfRegistryService.prototype = {
      *
      * @param column    The column to sort by.
      */
-    sortBuckets: function (sortEvent, column) {
+    sortBuckets: function (column) {
         if (column.sortable === true) {
             // toggle column sort order
             var sortOrder = column.sortOrder = (column.sortOrder === 'ASC') ? 
'DESC' : 'ASC';
@@ -405,17 +406,32 @@ NfRegistryService.prototype = {
         }
     },
 
+    /**
+     * Returns true if each bucket in the `filteredBuckets` are selected.
+     *
+     * @returns {boolean}
+     */
     allFilteredBucketsSelected: function () {
+        var selected = 0;
+        var allSelected = true;
         this.filteredBuckets.forEach(function (c) {
+            if (c.checked) {
+                selected++;
+            }
             if (c.checked === undefined || c.checked === false) {
-                return false;
+                allSelected =false;
             }
         });
 
-        return true;
+        this.disableMultiBucketActions = (selected > 0) ? false : true;
+        return allSelected;
     },
 
-    toggleBucketSelect: function (row) {
+    /**
+     * Checks all filtered buckets checked state and sets the 
`allBucketsSelected`
+     * property accordingly.
+     */
+    determineAllBucketsSelectedState: function () {
         if (this.allFilteredBucketsSelected()) {
             this.allBucketsSelected = true;
         } else {
@@ -423,6 +439,93 @@ NfRegistryService.prototype = {
         }
     },
 
+    /**
+     * Checks the `allBucketsSelected` property state and either selects
+     * or deselects all filtered buckets.
+     */
+    toggleBucketsSelectAll: function () {
+        if (this.allBucketsSelected) {
+            this.selectAllBuckets();
+        } else {
+            this.deselectAllBuckets();
+        }
+    },
+
+    /**
+     * Sets the `checked` property of each filtered bucket to true.
+     */
+    selectAllBuckets: function () {
+        this.filteredBuckets.forEach(function (c) {
+            c.checked = true;
+        });
+        this.disableMultiBucketActions = false;
+    },
+
+    /**
+     * Sets the `checked` property of each filtered bucket to false.
+     */
+    deselectAllBuckets: function () {
+        this.filteredBuckets.forEach(function (c) {
+            c.checked = false;
+        });
+        this.disableMultiBucketActions = true;
+    },
+
+    /**
+     * Removes a `searchTerm` from the `bucketsSearchTerms` and filters the 
`buckets`.
+     *
+     * @param {string} searchTerm The search term to remove.
+     */
+    bucketsSearchRemove: function (searchTerm) {
+        //only remove the first occurrence of the search term
+        var index = this.bucketsSearchTerms.indexOf(searchTerm);
+        if (index !== -1) {
+            this.bucketsSearchTerms.splice(index, 1);
+        }
+        this.filterBuckets();
+    },
+
+    /**
+     * Adds a `searchTerm` from the `bucketsSearchTerms` and filters the 
`buckets`.
+     *
+     * @param {string} searchTerm The search term to add.
+     */
+    bucketsSearchAdd: function (searchTerm) {
+        this.bucketsSearchTerms.push(searchTerm);
+        this.filterBuckets();
+    },
+
+    /**
+     * Deletes all versions of all flows of each selected bucket
+     */
+    deleteSelectedBuckets: function() {
+        var self = this;
+        this.dialogService.openConfirm({
+            title: 'Delete Buckets',
+            message: 'All versions of all flows of each selected bucket will 
be deleted.',
+            cancelButton: 'Cancel',
+            acceptButton: 'Delete',
+            acceptButtonColor: 'fds-warn'
+        }).afterClosed().subscribe(
+            function (accept) {
+                if (accept) {
+                    self.filteredBuckets.forEach(function (filteredBucket) {
+                        if (filteredBucket.checked) {
+                            
self.api.deleteBucket(filteredBucket.identifier).subscribe(function (response) {
+                                self.buckets = self.buckets.filter(function 
(bucket) {
+                                    return bucket.identifier !== 
filteredBucket.identifier;
+                                });
+                                self.filterBuckets();
+                                self.determineAllBucketsSelectedState();
+                            });
+                        }
+                    });
+
+                }
+            });
+
+    },
+
     sortUsers: function (sortEvent, column) {
         if (column.sortable) {
             var sortBy = column.name;
@@ -444,24 +547,11 @@ NfRegistryService.prototype = {
         if (index !== -1) {
             this.usersSearchTerms.splice(index, 1);
         }
-        this.usersCurrentPage = 1;
-        this.usersFromRow = 1;
-        this.usersPageSize = 1;
         this.filterUsers();
     },
 
     usersSearchAdd: function (searchTerm) {
         this.usersSearchTerms.push(searchTerm);
-        this.usersCurrentPage = 1;
-        this.usersFromRow = 1;
-        this.usersPageSize = 1;
-        this.filterUsers();
-    },
-
-    pageUsers: function (pagingEvent) {
-        this.usersFromRow = pagingEvent.fromRow;
-        this.usersCurrentPage = pagingEvent.page;
-        this.usersPageSize = pagingEvent.pageSize;
         this.filterUsers();
     },
 
@@ -476,7 +566,6 @@ NfRegistryService.prototype = {
             newData = filterData(newData, this.usersSearchTerms[i], true);
         }
         newData = this.dataTableService.sortData(newData, sortBy, sortOrder);
-        this.usersPageCount = newData.length;
         newData = this.dataTableService.pageData(newData, this.usersFromRow, 
this.usersCurrentPage * this.usersPageSize);
         this.filteredUsers = newData;
         this.getAutoCompleteUsers();

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/ede45ce6/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 b13dded..0a1a83f 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
@@ -39,6 +39,8 @@ var fdsCore = require('@fluid-design-system/core');
 var ngMoment = require('angular2-moment');
 var ngHttp = require('@angular/http');
 var rxjs = require('rxjs/Rx');
+var fdsDialogsModule = require('@fluid-design-system/dialogs');
+var ngRouter = require('@angular/router');
 
 describe('NfRegistry Service isolated unit tests', function () {
     var comp;
@@ -46,7 +48,7 @@ describe('NfRegistry Service isolated unit tests', function 
() {
     var nfRegistryService;
 
     beforeEach(function () {
-        nfRegistryService = new NfRegistryService();
+        nfRegistryService = new NfRegistryService({}, {}, {}, {});
     });
 
     it('should set the breadcrumb animation state', function () {
@@ -154,7 +156,7 @@ describe('NfRegistry Service isolated unit tests', function 
() {
         var column = {name: 'name', label: 'Name', sortable: true};
 
         // The function to test
-        var label = nfRegistryService.sortDroplets(column);
+        nfRegistryService.sortDroplets(column);
 
         //assertions
         expect(column.active).toBe(true);
@@ -164,6 +166,25 @@ describe('NfRegistry Service isolated unit tests', 
function () {
         expect(nfRegistryService.activeDropletColumn).toBe(column);
     });
 
+    it('should sort `buckets` by `column`', function () {
+        //Spy
+        spyOn(nfRegistryService, 'filterBuckets').and.callFake(function () {
+        });
+
+        // object to be updated by the test
+        var column = {name: 'name', label: 'Bucket Name', sortable: true};
+
+        // The function to test
+        nfRegistryService.sortBuckets(column);
+
+        //assertions
+        expect(column.active).toBe(true);
+        var filterBucketsCall = nfRegistryService.filterBuckets.calls.first();
+        expect(filterBucketsCall.args[0]).toBe('name');
+        expect(filterBucketsCall.args[1]).toBe('ASC');
+        expect(nfRegistryService.activeBucketsColumn).toBe(column);
+    });
+
     it('should generate the auto complete options for the droplet filter.', 
function () {
         //Setup the nfRegistryService state for this test
         nfRegistryService.filteredDroplets = [{
@@ -189,6 +210,163 @@ describe('NfRegistry Service isolated unit tests', 
function () {
         //assertions
         
expect(nfRegistryService.autoCompleteDroplets[0]).toBe(nfRegistryService.filteredDroplets[0].name);
     });
+
+    it('should generate the auto complete options for the bucket filter.', 
function () {
+        //Setup the nfRegistryService state for this test
+        nfRegistryService.filteredBuckets = [{
+            'identifier': '2e04b4fb-9513-47bb-aa74-1ae34616bfdc',
+            'name': 'Bucket #1',
+            'description': 'This is bucket #1'
+        }];
+
+        // The function to test
+        nfRegistryService.getAutoCompleteBuckets();
+
+        //assertions
+        
expect(nfRegistryService.autoCompleteBuckets[0]).toBe(nfRegistryService.filteredBuckets[0].name);
+    });
+
+    it('should check if all buckets are selected and return false.', function 
() {
+        //Setup the nfRegistryService state for this test
+        nfRegistryService.filteredBuckets = [{
+            'identifier': '2e04b4fb-9513-47bb-aa74-1ae34616bfdc',
+            'name': 'Bucket #1'
+        }, {
+            'identifier': '5c04b4fb-9513-47bb-aa74-1ae34616bfdc',
+            'name': 'Bucket #2'
+        }];
+
+        // The function to test
+        var allSelected = nfRegistryService.allFilteredBucketsSelected();
+
+        //assertions
+        expect(allSelected).toBe(false);
+        expect(nfRegistryService.disableMultiBucketActions).toBe(true);
+    });
+
+    it('should check if all buckets are selected and return true.', function 
() {
+        //Setup the nfRegistryService state for this test
+        nfRegistryService.filteredBuckets = [{
+            'identifier': '2e04b4fb-9513-47bb-aa74-1ae34616bfdc',
+            'name': 'Bucket #1',
+            'checked': true
+        }, {
+            'identifier': '5c04b4fb-9513-47bb-aa74-1ae34616bfdc',
+            'name': 'Bucket #2',
+            'checked': true
+        }];
+
+        // The function to test
+        var allSelected = nfRegistryService.allFilteredBucketsSelected();
+
+        //assertions
+        expect(allSelected).toBe(true);
+        expect(nfRegistryService.disableMultiBucketActions).toBe(false);
+    });
+
+    it('should set the `allBucketsSelected` state to true.', function () {
+        //Spy
+        spyOn(nfRegistryService, 
'allFilteredBucketsSelected').and.callFake(function () {
+        }).and.returnValue(true);
+
+        // The function to test
+        nfRegistryService.determineAllBucketsSelectedState();
+
+        //assertions
+        expect(nfRegistryService.allBucketsSelected).toBe(true);
+    });
+
+    it('should set the `allBucketsSelected` state to false.', function () {
+        //Spy
+        spyOn(nfRegistryService, 
'allFilteredBucketsSelected').and.callFake(function () {
+        }).and.returnValue(false);
+
+        // The function to test
+        nfRegistryService.determineAllBucketsSelectedState();
+
+        //assertions
+        expect(nfRegistryService.allBucketsSelected).toBe(false);
+    });
+
+    it('should toggle all bucket `checked` properties to true.', function () {
+        //Spy
+        spyOn(nfRegistryService, 'selectAllBuckets').and.callFake(function () {
+        });
+
+        nfRegistryService.allBucketsSelected = true;
+
+        // The function to test
+        nfRegistryService.toggleBucketsSelectAll();
+
+        //assertions
+        expect(nfRegistryService.selectAllBuckets).toHaveBeenCalled();
+    });
+
+    it('should toggle all bucket `checked` properties to false.', function () {
+        //Spy
+        spyOn(nfRegistryService, 'deselectAllBuckets').and.callFake(function 
() {
+        });
+
+        nfRegistryService.allBucketsSelected = false;
+
+        // The function to test
+        nfRegistryService.toggleBucketsSelectAll();
+
+        //assertions
+        expect(nfRegistryService.deselectAllBuckets).toHaveBeenCalled();
+    });
+
+    it('should select all buckets.', function () {
+        nfRegistryService.filteredBuckets = [{identifier: 1}];
+
+        // The function to test
+        nfRegistryService.selectAllBuckets();
+
+        //assertions
+        expect(nfRegistryService.filteredBuckets[0].checked).toBe(true);
+        expect(nfRegistryService.disableMultiBucketActions).toBe(false);
+    });
+
+    it('should deselect all buckets.', function () {
+        nfRegistryService.filteredBuckets = [{identifier: 1, checked: true}];
+
+        // The function to test
+        nfRegistryService.deselectAllBuckets();
+
+        //assertions
+        expect(nfRegistryService.filteredBuckets[0].checked).toBe(false);
+        expect(nfRegistryService.disableMultiBucketActions).toBe(true);
+    });
+
+    it('should add a bucket search term.', function () {
+        //Spy
+        spyOn(nfRegistryService, 'filterBuckets').and.callFake(function () {
+        });
+
+        // The function to test
+        nfRegistryService.bucketsSearchAdd('Bucket #1');
+
+        //assertions
+        expect(nfRegistryService.bucketsSearchTerms.length).toBe(1);
+        expect(nfRegistryService.bucketsSearchTerms[0]).toBe('Bucket #1');
+        expect(nfRegistryService.filterBuckets).toHaveBeenCalled();
+    });
+
+    it('should add a bucket search term.', function () {
+        //Spy
+        spyOn(nfRegistryService, 'filterBuckets').and.callFake(function () {
+        });
+
+        //set up the state
+        nfRegistryService.bucketsSearchTerms = ['Bucket #1'];
+
+        // The function to test
+        nfRegistryService.bucketsSearchRemove('Bucket #1');
+
+        //assertions
+        expect(nfRegistryService.bucketsSearchTerms.length).toBe(0);
+        expect(nfRegistryService.filterBuckets).toHaveBeenCalled();
+    });
 });
 
 describe('NfRegistry Service w/ Angular testing utils', function () {
@@ -253,7 +431,8 @@ describe('NfRegistry Service w/ Angular testing utils', 
function () {
 
     it('should retrieve the snapshot metadata for the given droplet.', 
ngCoreTesting.fakeAsync(function () {
         //Spy
-        spyOn(nfRegistryService.api, 
'getDropletSnapshotMetadata').and.callFake(function(){}).and.returnValue(rxjs.Observable.of([{
+        spyOn(nfRegistryService.api, 
'getDropletSnapshotMetadata').and.callFake(function () {
+        }).and.returnValue(rxjs.Observable.of([{
             version: 999
         }]));
 
@@ -288,7 +467,8 @@ describe('NfRegistry Service w/ Angular testing utils', 
function () {
                 return rxjs.Observable.of(true);
             }
         });
-        spyOn(nfRegistryService.api, 
'deleteDroplet').and.callFake(function(){}).and.returnValue(rxjs.Observable.of({identifier:
 '2e04b4fb-9513-47bb-aa74-1ae34616bfdc'}));
+        spyOn(nfRegistryService.api, 'deleteDroplet').and.callFake(function () 
{
+        }).and.returnValue(rxjs.Observable.of({identifier: 
'2e04b4fb-9513-47bb-aa74-1ae34616bfdc'}));
         spyOn(nfRegistryService, 'filterDroplets').and.callFake(function () {
         });
 
@@ -419,4 +599,156 @@ describe('NfRegistry Service w/ Angular testing utils', 
function () {
         expect(nfRegistryService.filteredDroplets[0].name).toBe('Flow #1');
         expect(nfRegistryService.getAutoCompleteDroplets).toHaveBeenCalled();
     }));
+
+    it('should execute a `delete` action on a bucket.', 
ngCoreTesting.fakeAsync(function () {
+        // from the root injector
+        var dialogService = 
ngCoreTesting.TestBed.get(fdsDialogsModule.FdsDialogService);
+
+        //Spy
+        spyOn(nfRegistryService, 'filterBuckets').and.callFake(function () {
+        });
+        spyOn(dialogService, 'openConfirm').and.callFake(function () {
+        }).and.returnValue({
+            afterClosed: function () {
+                return rxjs.Observable.of(true);
+            }
+        });
+        spyOn(nfRegistryService.api, 'deleteBucket').and.callFake(function () {
+        }).and.returnValue(rxjs.Observable.of({identifier: 
'2e04b4fb-9513-47bb-aa74-1ae34616bfdc'}));
+
+        // object to be updated by the test
+        var bucket = {identifier: '999'};
+
+        // set up the bucket to be deleted
+        nfRegistryService.buckets = [bucket, {identifier: 1}];
+
+        // The function to test
+        nfRegistryService.executeBucketAction({name: 'delete'}, bucket);
+
+        // wait for async openConfirm call
+        ngCoreTesting.tick();
+
+        //inform angular to detect changes
+        fixture.detectChanges();
+
+        // wait for async deleteBucket call
+        ngCoreTesting.tick();
+
+        //inform angular to detect changes
+        fixture.detectChanges();
+
+        //assertions
+        expect(dialogService.openConfirm).toHaveBeenCalled();
+        expect(nfRegistryService.api.deleteBucket).toHaveBeenCalled();
+        expect(nfRegistryService.filterBuckets).toHaveBeenCalled();
+        expect(nfRegistryService.buckets.length).toBe(1);
+        expect(nfRegistryService.buckets[0].identifier).toBe(1);
+    }));
+
+    it('should execute a `permissions` action on a bucket.', function () {
+        // from the root injector
+        var router = ngCoreTesting.TestBed.get(ngRouter.Router);
+
+        //Spy
+        spyOn(router, 'navigateByUrl').and.callFake(function () {
+        });
+
+        // object to be updated by the test
+        var bucket = {identifier: '999'};
+
+        // The function to test
+        nfRegistryService.executeBucketAction({name: 'permissions', type: 
'sidenav'}, bucket);
+
+        //assertions
+        var navigateByUrlCall = router.navigateByUrl.calls.first();
+        
expect(navigateByUrlCall.args[0]).toBe('/nifi-registry/administration/workflow(sidenav:bucket/permissions/999)');
+    });
+
+    it('should filter buckets by name.', ngCoreTesting.fakeAsync(function () {
+        //Setup the nfRegistryService state for this test
+        nfRegistryService.bucketsSearchTerms = ['Bucket #1'];
+        nfRegistryService.buckets = [{
+            'identifier': '2e04b4fb-9513-47bb-aa74-1ae34616bfdc',
+            'name': 'Bucket #1',
+            'description': 'This is bucket #1',
+            'checked': true
+        }, {
+            'identifier': '5d04b4fb-9513-47bb-aa74-1ae34616bfdc',
+            'name': 'Bucket #2',
+            'description': 'This is bucket #2',
+            'checked': true
+        }];
+
+        //Spy
+        spyOn(nfRegistryService, 'getAutoCompleteBuckets');
+
+        //assertion
+        expect(nfRegistryService.disableMultiBucketActions).toBe(true);
+
+        // The function to test
+        nfRegistryService.filterBuckets();
+
+        // wait for async nfRegistryService.api.deleteDroplet call
+        ngCoreTesting.tick();
+
+        //inform angular to detect changes
+        fixture.detectChanges();
+
+        //assertions
+        expect(nfRegistryService.filteredBuckets.length).toBe(1);
+        expect(nfRegistryService.filteredBuckets[0].name).toBe('Bucket #1');
+        expect(nfRegistryService.getAutoCompleteBuckets).toHaveBeenCalled();
+        expect(nfRegistryService.disableMultiBucketActions).toBe(false);
+    }));
+
+    it('should delete all selected buckets.', ngCoreTesting.fakeAsync(function 
() {
+        // from the root injector
+        var dialogService = 
ngCoreTesting.TestBed.get(fdsDialogsModule.FdsDialogService);
+
+        //Spy
+        spyOn(nfRegistryService, 'filterBuckets').and.callFake(function () {
+        });
+        spyOn(nfRegistryService, 
'determineAllBucketsSelectedState').and.callFake(function () {
+        });
+        spyOn(dialogService, 'openConfirm').and.callFake(function () {
+        }).and.returnValue({
+            afterClosed: function () {
+                return rxjs.Observable.of(true);
+            }
+        });
+        spyOn(nfRegistryService.api, 'deleteBucket').and.callFake(function () {
+        }).and.returnValue(rxjs.Observable.of({identifier: 999}));
+
+        // object to be updated by the test
+        var bucket = {identifier: 999, checked: true};
+
+        // set up the bucket to be deleted
+        nfRegistryService.buckets = nfRegistryService.filteredBuckets = 
[bucket, {identifier: 1}];
+
+        // The function to test
+        nfRegistryService.deleteSelectedBuckets();
+
+        // wait for async openConfirm call
+        ngCoreTesting.tick();
+
+        //inform angular to detect changes
+        fixture.detectChanges();
+
+        // wait for async deleteBucket call
+        ngCoreTesting.tick();
+
+        //inform angular to detect changes
+        fixture.detectChanges();
+
+        //assertions
+        expect(dialogService.openConfirm).toHaveBeenCalled();
+        expect(nfRegistryService.api.deleteBucket).toHaveBeenCalled();
+        expect(nfRegistryService.api.deleteBucket.calls.count()).toBe(1);
+        expect(nfRegistryService.filterBuckets).toHaveBeenCalled();
+        expect(nfRegistryService.filterBuckets.calls.count()).toBe(1);
+        expect(nfRegistryService.disableMultiBucketActions).toBe(true);
+        
expect(nfRegistryService.determineAllBucketsSelectedState).toHaveBeenCalled();
+        expect(nfRegistryService.buckets.length).toBe(1);
+        expect(nfRegistryService.buckets[0].identifier).toBe(1);
+    }));
 });
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/ede45ce6/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 e1e7fb5..5482075 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
@@ -96,6 +96,7 @@
             
'nifi-registry/components/administration/users/add/nf-registry-add-user.js': 
'components/administration/users/add/nf-registry-add-user.js',
             
'nifi-registry/components/administration/users/details/nf-registry-user-details.js':
 'components/administration/users/details/nf-registry-user-details.js',
             
'nifi-registry/components/administration/users/permissions/nf-registry-user-permissions.js':
 'components/administration/users/permissions/nf-registry-user-permissions.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/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',

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/ede45ce6/nifi-registry-web-ui/src/main/webapp/theming/components/administration/general/_structureElements.scss
----------------------------------------------------------------------
diff --git 
a/nifi-registry-web-ui/src/main/webapp/theming/components/administration/general/_structureElements.scss
 
b/nifi-registry-web-ui/src/main/webapp/theming/components/administration/general/_structureElements.scss
deleted file mode 100644
index ab3548d..0000000
--- 
a/nifi-registry-web-ui/src/main/webapp/theming/components/administration/general/_structureElements.scss
+++ /dev/null
@@ -1,25 +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.
- */
-
-#nifi-registry-general-administration-perspective {
-    position: absolute;
-    top: 79px;
-    left: 50px;
-    right: calc(50% - 5px);
-    bottom: 20px;
-    background: white;
-}

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/ede45ce6/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 650593f..15c3c2d 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
@@ -27,8 +27,8 @@
 #nifi-registry-users-administration-list-container {
     overflow-y: auto;
     position: absolute;
-    bottom: 49px;
-    top: 124px;
+    bottom: 30px;
+    top: 138px;
     left: 30px;
     right: 30px;
     overflow-x: hidden;

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/ede45ce6/nifi-registry-web-ui/src/main/webapp/theming/components/administration/workflow/_structureElements.scss
----------------------------------------------------------------------
diff --git 
a/nifi-registry-web-ui/src/main/webapp/theming/components/administration/workflow/_structureElements.scss
 
b/nifi-registry-web-ui/src/main/webapp/theming/components/administration/workflow/_structureElements.scss
index 0384079..446f9a9 100644
--- 
a/nifi-registry-web-ui/src/main/webapp/theming/components/administration/workflow/_structureElements.scss
+++ 
b/nifi-registry-web-ui/src/main/webapp/theming/components/administration/workflow/_structureElements.scss
@@ -19,43 +19,31 @@
     position: absolute;
     top: 79px;
     left: 50px;
-    right: calc(50% - 5px);
+    right: 20px;
     bottom: 20px;
     background: white;
 }
 
-//#nifi-registry-workflow-administration-perspective-certifications-container {
-//    position: absolute;
-//    top: 79px;
-//    left: calc(50% + 25px);
-//    right: 20px;
-//    bottom: 20px;
-//    background: white;
-//}
-
 #nifi-registry-workflow-administration-buckets-list-container {
     overflow-y: auto;
     position: absolute;
     bottom: 30px;
-    top: 171px;
+    top: 138px;
     left: 30px;
     right: 30px;
     overflow-x: hidden;
 }
 
-//#nifi-registry-workflow-administration-certifications-list-container {
-//    overflow-y: auto;
-//    position: absolute;
-//    bottom: 30px;
-//    top: 171px;
-//    left: 30px;
-//    right: 30px;
-//    overflow-x: hidden;
-//}
-
 #nf-registry-workflow-bucket-permissions-side-nav-container {
     position: absolute;
     bottom: 15px;
     right: 10px;
 }
 
+#nifi-registry-workflow-bucket-list-paging-bar {
+    position: absolute;
+    bottom: 0;
+    left: 0;
+    right: 0;
+}
+

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/ede45ce6/nifi-registry-web-ui/src/main/webapp/theming/nf-registry.scss
----------------------------------------------------------------------
diff --git a/nifi-registry-web-ui/src/main/webapp/theming/nf-registry.scss 
b/nifi-registry-web-ui/src/main/webapp/theming/nf-registry.scss
index 8d9e878..5b8db9e 100644
--- a/nifi-registry-web-ui/src/main/webapp/theming/nf-registry.scss
+++ b/nifi-registry-web-ui/src/main/webapp/theming/nf-registry.scss
@@ -23,7 +23,6 @@
 @import 'structureElements';
 @import 'helperClasses';
 @import 'components/administration/structureElements';
-@import 'components/administration/general/structureElements';
 @import 'components/administration/users/structureElements';
 @import 'components/administration/workflow/structureElements';
 @import 'components/explorer/grid-list/structureElements';

Reply via email to