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';
