http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/6f26290d/nifi-registry-core/nifi-registry-web-ui/src/main/webapp/components/administration/nf-registry-administration.html ---------------------------------------------------------------------- diff --git a/nifi-registry-core/nifi-registry-web-ui/src/main/webapp/components/administration/nf-registry-administration.html b/nifi-registry-core/nifi-registry-web-ui/src/main/webapp/components/administration/nf-registry-administration.html new file mode 100644 index 0000000..23f40a0 --- /dev/null +++ b/nifi-registry-core/nifi-registry-web-ui/src/main/webapp/components/administration/nf-registry-administration.html @@ -0,0 +1,40 @@ +<!-- +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-administration-perspective"> + <mat-button-toggle-group name="nifi-registry-administration-perspective" fxLayout="row" + fxLayoutAlign="space-between center" class="tab-toggle-group"> + <mat-button-toggle + [disabled]="!nfRegistryService.currentUser.resourcePermissions.buckets.canRead" + [matTooltip]="'Manage NiFi Registry buckets.'" + [checked]="nfRegistryService.adminPerspective === 'workflow'" value="workflow" + class="uppercase" + (change)="navigateToAdminPerspective($event)" + i18n="Workflow administration tab|A description of the type of administration options available.@@nf-admin-workflow-tab-title"> + Buckets + </mat-button-toggle> + <mat-button-toggle + [disabled]="nfRegistryService.currentUser.anonymous || !nfRegistryService.currentUser.resourcePermissions.tenants.canRead" + [matTooltip]="getUserTooltip()" + [checked]="nfRegistryService.adminPerspective === 'users'" value="users" class="uppercase" + (change)="navigateToAdminPerspective($event)" + i18n="Users administration tab|A description of the type of administration options available.@@nf-admin-users-tab-title"> + Users + </mat-button-toggle> + </mat-button-toggle-group> +</div> +<router-outlet></router-outlet>
http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/6f26290d/nifi-registry-core/nifi-registry-web-ui/src/main/webapp/components/administration/nf-registry-administration.js ---------------------------------------------------------------------- diff --git a/nifi-registry-core/nifi-registry-web-ui/src/main/webapp/components/administration/nf-registry-administration.js b/nifi-registry-core/nifi-registry-web-ui/src/main/webapp/components/administration/nf-registry-administration.js new file mode 100644 index 0000000..fa37658 --- /dev/null +++ b/nifi-registry-core/nifi-registry-web-ui/src/main/webapp/components/administration/nf-registry-administration.js @@ -0,0 +1,98 @@ +/* + * 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 nfRegistryAnimations = require('nifi-registry/nf-registry.animations.js'); +var ngRouter = require('@angular/router'); + +/** + * NfRegistryAdministration constructor. + * + * @param nfRegistryService The nf-registry.service module. + * @param router The angular router module. + * @constructor + */ +function NfRegistryAdministration(nfRegistryService, router) { + //Services + this.router = router; + this.nfRegistryService = nfRegistryService; +}; + +NfRegistryAdministration.prototype = { + constructor: NfRegistryAdministration, + + /** + * Initialize the component. + */ + ngOnInit: function () { + var self = this; + this.nfRegistryService.perspective = 'administration'; + this.nfRegistryService.setBreadcrumbState('in'); + }, + + /** + * Destroy the component. + */ + ngOnDestroy: function () { + this.nfRegistryService.perspective = ''; + this.nfRegistryService.setBreadcrumbState('out'); + }, + + /** + * Navigates to admin perspective. + * + * @param $event + */ + navigateToAdminPerspective: function($event) { + this.router.navigateByUrl('nifi-registry/administration/' + $event.value); + }, + + /** + * Generate the user tab tooltip. + * + * @returns {*} + */ + getUserTooltip: function() { + if(this.nfRegistryService.currentUser.anonymous) { + return 'Please configure NiFi Registry security to enable.'; + } + else { + if(!this.nfRegistryService.currentUser.resourcePermissions.tenants.canRead) { + return 'You do not have permission. Please contact your System Administrator.' + } else { + return 'Manage NiFi Registry users and groups.' + } + } + } +}; + +NfRegistryAdministration.annotations = [ + new ngCore.Component({ + template: require('./nf-registry-administration.html!text'), + animations: [nfRegistryAnimations.slideInLeftAnimation], + host: { + '[@routeAnimation]': 'routeAnimation' + } + }) +]; + +NfRegistryAdministration.parameters = [ + NfRegistryService, + ngRouter.Router +]; + +module.exports = NfRegistryAdministration; http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/6f26290d/nifi-registry-core/nifi-registry-web-ui/src/main/webapp/components/administration/nf-registry-administration.spec.js ---------------------------------------------------------------------- diff --git a/nifi-registry-core/nifi-registry-web-ui/src/main/webapp/components/administration/nf-registry-administration.spec.js b/nifi-registry-core/nifi-registry-web-ui/src/main/webapp/components/administration/nf-registry-administration.spec.js new file mode 100644 index 0000000..fbf228a --- /dev/null +++ b/nifi-registry-core/nifi-registry-web-ui/src/main/webapp/components/administration/nf-registry-administration.spec.js @@ -0,0 +1,146 @@ +/* + * 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 ngCommonHttp = require('@angular/common/http'); +var NfRegistryTokenInterceptor = require('nifi-registry/services/nf-registry.token.interceptor.js'); +var NfStorage = require('nifi-registry/services/nf-storage.service.js'); +var ngPlatformBrowser = require('@angular/platform-browser'); +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/dialogs/add-user/nf-registry-add-user.js'); +var NfRegistryManageUser = require('nifi-registry/components/administration/users/sidenav/manage-user/nf-registry-manage-user.js'); +var NfRegistryManageGroup = require('nifi-registry/components/administration/users/sidenav/manage-group/nf-registry-manage-group.js'); +var NfRegistryManageBucket = require('nifi-registry/components/administration/workflow/sidenav/manage-bucket/nf-registry-manage-bucket.js'); +var NfRegistryWorkflowAdministration = require('nifi-registry/components/administration/workflow/nf-registry-workflow-administration.js'); +var NfRegistryGridListViewer = require('nifi-registry/components/explorer/grid-list/registry/nf-registry-grid-list-viewer.js'); +var NfRegistryBucketGridListViewer = require('nifi-registry/components/explorer/grid-list/registry/nf-registry-bucket-grid-list-viewer.js'); +var NfRegistryDropletGridListViewer = require('nifi-registry/components/explorer/grid-list/registry/nf-registry-droplet-grid-list-viewer.js'); +var fdsCore = require('@flow-design-system/core'); +var ngMoment = require('angular2-moment'); +var rxjs = require('rxjs/Rx'); +var NfLoginComponent = require('nifi-registry/components/login/nf-registry-login.js'); +var NfUserLoginComponent = require('nifi-registry/components/login/dialogs/nf-registry-user-login.js'); + +describe('NfRegistryAdministration Component', function () { + var comp; + var fixture; + var de; + var el; + var nfRegistryService; + var nfRegistryApi; + + beforeEach(function () { + ngCoreTesting.TestBed.configureTestingModule({ + imports: [ + ngMoment.MomentModule, + ngCommonHttp.HttpClientModule, + fdsCore, + NfRegistryRoutes + ], + declarations: [ + NfRegistry, + NfRegistryExplorer, + NfRegistryAdministration, + NfRegistryUsersAdministration, + NfRegistryManageUser, + NfRegistryManageGroup, + NfRegistryManageBucket, + NfRegistryAddUser, + NfRegistryWorkflowAdministration, + NfRegistryGridListViewer, + NfRegistryBucketGridListViewer, + NfRegistryDropletGridListViewer, + NfPageNotFoundComponent, + NfLoginComponent, + NfUserLoginComponent + ], + providers: [ + NfRegistryService, + NfRegistryApi, + NfStorage, + { + provide: ngCommonHttp.HTTP_INTERCEPTORS, + useClass: NfRegistryTokenInterceptor, + multi: true + }, + { + provide: ngCommon.APP_BASE_HREF, + useValue: '/' + } + ] + }); + + fixture = ngCoreTesting.TestBed.createComponent(NfRegistryAdministration); + + // test instance + comp = fixture.componentInstance; + + // from the root injector + nfRegistryService = ngCoreTesting.TestBed.get(NfRegistryService); + nfRegistryApi = ngCoreTesting.TestBed.get(NfRegistryApi); + de = fixture.debugElement.query(ngPlatformBrowser.By.css('#nifi-registry-administration-perspective')); + el = de.nativeElement; + + // Spy + spyOn(nfRegistryApi, 'getDroplets').and.callFake(function () { + }).and.returnValue(rxjs.Observable.of([{ + "identifier": "2e04b4fb-9513-47bb-aa74-1ae34616bfdc", + "name": "Flow #1", + "description": "This is flow #1", + "bucketIdentifier": "2f7f9e54-dc09-4ceb-aa58-9fe581319cdc", + "createdTimestamp": 1505931890999, + "modifiedTimestamp": 1505931890999, + "type": "FLOW", + "snapshotMetadata": null, + "link": { + "params": { + "rel": "self" + }, + "href": "flows/2e04b4fb-9513-47bb-aa74-1ae34616bfdc" + } + }])); + }); + + it('should have a defined component', function () { + fixture.detectChanges(); + + //assertions + expect(comp).toBeDefined(); + expect(nfRegistryService.perspective).toBe('administration'); + expect(nfRegistryService.breadCrumbState).toBe('in'); + expect(de).toBeDefined(); + }); + + it('should destroy the component', function () { + fixture.detectChanges(); + + // The function to test + comp.ngOnDestroy(); + + //assertions + expect(nfRegistryService.perspective).toBe(''); + expect(nfRegistryService.breadCrumbState).toBe('out'); + }); +}); \ No newline at end of file http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/6f26290d/nifi-registry-core/nifi-registry-web-ui/src/main/webapp/components/administration/users/dialogs/add-user-to-groups/nf-registry-add-user-to-groups.html ---------------------------------------------------------------------- diff --git a/nifi-registry-core/nifi-registry-web-ui/src/main/webapp/components/administration/users/dialogs/add-user-to-groups/nf-registry-add-user-to-groups.html b/nifi-registry-core/nifi-registry-web-ui/src/main/webapp/components/administration/users/dialogs/add-user-to-groups/nf-registry-add-user-to-groups.html new file mode 100644 index 0000000..70e59ed --- /dev/null +++ b/nifi-registry-core/nifi-registry-web-ui/src/main/webapp/components/administration/users/dialogs/add-user-to-groups/nf-registry-add-user-to-groups.html @@ -0,0 +1,81 @@ +<!-- +Licensed to the Apache Software Foundation (ASF) under one or more +contributor license agreements. See the NOTICE file distributed with +this work for additional information regarding copyright ownership. +The ASF licenses this file to You under the Apache License, Version 2.0 +(the "License"); you may not use this file except in compliance with +the License. You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +--> + +<div id="nifi-registry-admin-add-selected-users-to-group-dialog"> + <div class="pad-bottom-md" fxLayout="row" fxLayoutAlign="space-between center"> + <span class="md-card-title">Add user to groups</span> + <button mat-icon-button (click)="cancel()"> + <mat-icon color="primary">close</mat-icon> + </button> + </div> + <div *ngIf="filteredUserGroups.length > 0" class="pad-bottom-md"> + <div id="nifi-registry-users-administration-list-container-column-header" class="td-data-table"> + <div class="td-data-table-column" (click)="sortUserGroups(column)" + *ngFor="let column of userGroupsColumns" + fxFlex="{{column.width}}"> + {{column.label}} + <i *ngIf="column.active && column.sortable && column.sortOrder === 'ASC'" class="fa fa-caret-up" + aria-hidden="true"></i> + <i *ngIf="column.active && column.sortable && column.sortOrder === 'DESC'" class="fa fa-caret-down" + aria-hidden="true"></i> + </div> + <div class="td-data-table-column"> + <mat-checkbox [(ngModel)]="allGroupsSelected" + (checked)="allGroupsSelected" + (change)="toggleUserGroupsSelectAll()"></mat-checkbox> + </div> + </div> + <div id="nifi-registry-add-selected-users-to-group-list-container"> + <div fxLayout="row" fxLayoutAlign="space-between center" + class="td-data-table-row" + [ngClass]="{'selected' : group.checked}" + *ngFor="let group of filteredUserGroups" + (click)="group.checked = !group.checked;determineAllUserGroupsSelectedState();"> + <div class="td-data-table-cell" *ngFor="let column of userGroupsColumns" + fxFlex="{{column.width}}"> + <div class="ellipsis" matTooltip="{{column.format ? column.format(group[column.name]) : group[column.name]}}"> + <i class="fa fa-users push-right-sm" aria-hidden="true"></i>{{column.format ? + column.format(group[column.name]) : group[column.name]}} + </div> + </div> + <div class="td-data-table-cell"> + <mat-checkbox [(ngModel)]="group.checked" + [checked]="group.checked" + (change)="determineAllUserGroupsSelectedState()" + (click)="group.checked = !group.checked;determineAllUserGroupsSelectedState()"> + </mat-checkbox> + </div> + </div> + </div> + </div> + <div class="mat-padding push-bottom-md" *ngIf="filteredUserGroups.length === 0" layout="row" + layout-align="center center"> + <h3>User belongs to all groups.</h3> + </div> + <div fxLayout="row"> + <span fxFlex></span> + <button (click)="cancel()" color="fds-regular" mat-raised-button + i18n="Cancel addition of selected users to group|A button for cancelling the addition of selected users to a group in the registry.@@nf-admin-workflow-cancel-add-selected-users-to-group-button"> + Cancel + </button> + <button [disabled]="isAddToSelectedGroupsDisabled" class="push-left-sm" (click)="addToSelectedGroups()" + color="fds-primary" mat-raised-button + i18n="Add selected users to group button|A button for adding users to an existing group in the registry.@@nf-admin-workflow-add-selected-users-to-group-button"> + Add + </button> + </div> +</div> http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/6f26290d/nifi-registry-core/nifi-registry-web-ui/src/main/webapp/components/administration/users/dialogs/add-user-to-groups/nf-registry-add-user-to-groups.js ---------------------------------------------------------------------- diff --git a/nifi-registry-core/nifi-registry-web-ui/src/main/webapp/components/administration/users/dialogs/add-user-to-groups/nf-registry-add-user-to-groups.js b/nifi-registry-core/nifi-registry-web-ui/src/main/webapp/components/administration/users/dialogs/add-user-to-groups/nf-registry-add-user-to-groups.js new file mode 100644 index 0000000..e808803 --- /dev/null +++ b/nifi-registry-core/nifi-registry-web-ui/src/main/webapp/components/administration/users/dialogs/add-user-to-groups/nf-registry-add-user-to-groups.js @@ -0,0 +1,254 @@ +/* + * 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 covalentCore = require('@covalent/core'); +var NfRegistryApi = require('nifi-registry/services/nf-registry.api.js'); +var ngCore = require('@angular/core'); +var fdsSnackBarsModule = require('@flow-design-system/snackbars'); +var NfRegistryService = require('nifi-registry/services/nf-registry.service.js'); +var ngMaterial = require('@angular/material'); +var $ = require('jquery'); + +/** + * NfRegistryAddUserToGroups constructor. + * + * @param nfRegistryApi The api service. + * @param tdDataTableService The covalent data table service module. + * @param nfRegistryService The nf-registry.service module. + * @param matDialogRef The angular material dialog ref. + * @param fdsSnackBarService The FDS snack bar service module. + * @param data The data passed into this component. + * @constructor + */ +function NfRegistryAddUserToGroups(nfRegistryApi, tdDataTableService, nfRegistryService, matDialogRef, fdsSnackBarService, data) { + //Services + this.dataTableService = tdDataTableService; + this.snackBarService = fdsSnackBarService; + this.nfRegistryService = nfRegistryService; + this.nfRegistryApi = nfRegistryApi; + this.dialogRef = matDialogRef; + this.data = data; + + // local state + //make an independent copy of the groups for sorting and selecting within the scope of this component + this.groups = $.extend(true, [], this.nfRegistryService.groups); + this.filteredUserGroups = []; + this.isAddToSelectedGroupsDisabled = true; + this.userGroupsSearchTerms = []; + this.allGroupsSelected = false; + this.userGroupsColumns = [ + { + name: 'identity', + label: 'Display Name', + sortable: true, + tooltip: 'Group name.', + width: 100 + } + ]; +}; + +NfRegistryAddUserToGroups.prototype = { + constructor: NfRegistryAddUserToGroups, + + /** + * Initialize the component. + */ + ngOnInit: function () { + var self = this; + + // filter out any groups that + // 1) that are not configurable + self.groups = self.groups.filter(function (group) { + return (group.configurable) ? true : false + }); + // 2) the user already belongs to + this.data.user.userGroups.forEach(function (userGroup) { + self.groups = self.groups.filter(function (group) { + return (group.identifier !== userGroup.identifier) ? true : false + }); + }); + + this.filterGroups(); + this.deselectAllUserGroups(); + this.determineAllUserGroupsSelectedState(); + }, + + /** + * Filter groups. + * + * @param {string} [sortBy] The column name to sort `userGroupsColumns` by. + * @param {string} [sortOrder] The order. Either 'ASC' or 'DES' + */ + filterGroups: function (sortBy, sortOrder) { + // if `sortOrder` is `undefined` then use 'ASC' + if (sortOrder === undefined) { + sortOrder = 'ASC' + } + // if `sortBy` is `undefined` then find the first sortable column in `dropletColumns` + if (sortBy === undefined) { + var arrayLength = this.userGroupsColumns.length; + for (var i = 0; i < arrayLength; i++) { + if (this.userGroupsColumns[i].sortable === true) { + sortBy = this.userGroupsColumns[i].name; + //only one column can be actively sorted so we reset all to inactive + this.userGroupsColumns.forEach(function (c) { + c.active = false; + }); + //and set this column as the actively sorted column + this.userGroupsColumns[i].active = true; + this.userGroupsColumns[i].sortOrder = sortOrder; + break; + } + } + } + + var newUserGroupsData = this.groups; + + for (var i = 0; i < this.userGroupsSearchTerms.length; i++) { + newUserGroupsData = this.dataTableService.filterData(newUserGroupsData, this.userGroupsSearchTerms[i], true); + } + + newUserGroupsData = this.dataTableService.sortData(newUserGroupsData, sortBy, sortOrder); + this.filteredUserGroups = newUserGroupsData; + }, + + /** + * Sort `filteredUserGroups` by `column`. + * + * @param column The column to sort by. + */ + sortUserGroups: function (column) { + if (column.sortable) { + var sortBy = column.name; + var sortOrder = column.sortOrder = (column.sortOrder === 'ASC') ? 'DESC' : 'ASC'; + this.filterGroups(sortBy, sortOrder); + } + }, + + /** + * Checks the `allGroupsSelected` property state and either selects + * or deselects each of the `filteredUserGroups`. + */ + toggleUserGroupsSelectAll: function () { + if (this.allGroupsSelected) { + this.selectAllUserGroups(); + } else { + this.deselectAllUserGroups(); + } + }, + + /** + * Sets the `checked` property of each of the `filteredUserGroups` to true + * and sets the `isAddToSelectedGroupsDisabled` and the `allGroupsSelected` + * properties accordingly. + */ + selectAllUserGroups: function () { + this.filteredUserGroups.forEach(function (c) { + c.checked = true; + }); + this.isAddToSelectedGroupsDisabled = false; + this.allGroupsSelected = true; + }, + + /** + * Sets the `checked` property of each group to false + * and sets the `isAddToSelectedGroupsDisabled` and the `allGroupsSelected` + * properties accordingly. + */ + deselectAllUserGroups: function () { + this.filteredUserGroups.forEach(function (c) { + c.checked = false; + }); + this.isAddToSelectedGroupsDisabled = true; + this.allGroupsSelected = false; + }, + + /** + * Checks of each of the `filteredUserGroups`'s checked property state + * and sets the `allBucketsSelected` and `isAddToSelectedGroupsDisabled` + * property accordingly. + */ + determineAllUserGroupsSelectedState: function () { + var selected = 0; + var allSelected = true; + this.filteredUserGroups.forEach(function (c) { + if (c.checked) { + selected++; + } + if (c.checked === undefined || c.checked === false) { + allSelected = false; + } + }); + + if (selected > 0) { + this.isAddToSelectedGroupsDisabled = false; + } else { + this.isAddToSelectedGroupsDisabled = true; + } + + this.allGroupsSelected = allSelected; + }, + + /** + * Adds users to each of the selected groups. + */ + addToSelectedGroups: function () { + var self = this; + var selectedGroups = this.filteredUserGroups.filter(function (filteredUserGroup) { + return filteredUserGroup.checked; + }); + selectedGroups.forEach(function (selectedGroup) { + selectedGroup.users.push(self.data.user); + self.nfRegistryApi.updateUserGroup(selectedGroup.identifier, selectedGroup.identity, selectedGroup.users).subscribe(function (group) { + self.dialogRef.close(); + var snackBarRef = self.snackBarService.openCoaster({ + title: 'Success', + message: 'User has been added to the ' + group.identity + ' group.', + verticalPosition: 'bottom', + horizontalPosition: 'right', + icon: 'fa fa-check-circle-o', + color: '#1EB475', + duration: 3000 + }); + }); + }); + }, + + /** + * Cancel adding selected users to groups and close the dialog. + */ + cancel: function () { + this.dialogRef.close(); + } +}; + +NfRegistryAddUserToGroups.annotations = [ + new ngCore.Component({ + template: require('./nf-registry-add-user-to-groups.html!text') + }) +]; + +NfRegistryAddUserToGroups.parameters = [ + NfRegistryApi, + covalentCore.TdDataTableService, + NfRegistryService, + ngMaterial.MatDialogRef, + fdsSnackBarsModule.FdsSnackBarService, + ngMaterial.MAT_DIALOG_DATA +]; + +module.exports = NfRegistryAddUserToGroups; http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/6f26290d/nifi-registry-core/nifi-registry-web-ui/src/main/webapp/components/administration/users/dialogs/add-user-to-groups/nf-registry-add-user-to-groups.spec.js ---------------------------------------------------------------------- diff --git a/nifi-registry-core/nifi-registry-web-ui/src/main/webapp/components/administration/users/dialogs/add-user-to-groups/nf-registry-add-user-to-groups.spec.js b/nifi-registry-core/nifi-registry-web-ui/src/main/webapp/components/administration/users/dialogs/add-user-to-groups/nf-registry-add-user-to-groups.spec.js new file mode 100644 index 0000000..1e0140d --- /dev/null +++ b/nifi-registry-core/nifi-registry-web-ui/src/main/webapp/components/administration/users/dialogs/add-user-to-groups/nf-registry-add-user-to-groups.spec.js @@ -0,0 +1,172 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the 'License'); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an 'AS IS' BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +var NfRegistryApi = require('nifi-registry/services/nf-registry.api.js'); +var NfRegistryService = require('nifi-registry/services/nf-registry.service.js'); +var NfRegistryAddUserToGroups = require('nifi-registry/components/administration/users/dialogs/add-user-to-groups/nf-registry-add-user-to-groups.js'); +var rxjs = require('rxjs/Rx'); +var covalentCore = require('@covalent/core'); +var fdsSnackBarsModule = require('@flow-design-system/snackbars'); + +describe('NfRegistryAddUserToGroups Component isolated unit tests', function () { + var comp; + var nfRegistryService; + var nfRegistryApi; + var snackBarService; + var dataTableService; + + beforeEach(function () { + nfRegistryService = new NfRegistryService(); + // setup the nfRegistryService + nfRegistryService.user = {identifier: 3, identity: 'User 3', userGroups: []}; + nfRegistryService.groups = [{identifier: 1, identity: 'Group 1', configurable: true, checked: true, users: []}]; + + nfRegistryApi = new NfRegistryApi(); + snackBarService = new fdsSnackBarsModule.FdsSnackBarService(); + dataTableService = new covalentCore.TdDataTableService(); + comp = new NfRegistryAddUserToGroups(nfRegistryApi, dataTableService, nfRegistryService, { + close: function () { + } + }, snackBarService, {user: nfRegistryService.user}); + + // Spy + spyOn(nfRegistryApi, 'getUserGroup').and.callFake(function () { + }).and.returnValue(rxjs.Observable.of({identifier: 1, identity: 'Group 1'})); + spyOn(nfRegistryApi, 'updateUserGroup').and.callFake(function () { + }).and.returnValue(rxjs.Observable.of({identifier: 1, identity: 'Group 1'})); + spyOn(comp.dialogRef, 'close'); + spyOn(comp.snackBarService, 'openCoaster'); + spyOn(comp, 'filterGroups').and.callThrough(); + + // initialize the component + comp.ngOnInit(); + + //assertions + expect(comp.filterGroups).toHaveBeenCalled(); + expect(comp.filteredUserGroups[0].identity).toEqual('Group 1'); + expect(comp.filteredUserGroups.length).toBe(1); + expect(comp).toBeDefined(); + }); + + it('should make a call to the api to add user to selected groups', function () { + // select a group + comp.filteredUserGroups[0].checked = true; + + // the function to test + comp.addToSelectedGroups(); + + //assertions + expect(comp.dialogRef.close).toHaveBeenCalled(); + expect(comp.snackBarService.openCoaster).toHaveBeenCalled(); + }); + + it('should determine if all groups are selected', function () { + // select a group + comp.filteredUserGroups[0].checked = true; + + // the function to test + comp.determineAllUserGroupsSelectedState(); + + //assertions + expect(comp.allGroupsSelected).toBe(true); + expect(comp.isAddToSelectedGroupsDisabled).toBe(false); + }); + + it('should determine if all groups are not selected', function () { + // select a group + comp.filteredUserGroups[0].checked = false; + + // the function to test + comp.determineAllUserGroupsSelectedState(); + + //assertions + expect(comp.allGroupsSelected).toBe(false); + expect(comp.isAddToSelectedGroupsDisabled).toBe(true); + }); + + it('should select all groups.', function () { + // The function to test + comp.selectAllUserGroups(); + + //assertions + expect(comp.filteredUserGroups[0].checked).toBe(true); + expect(comp.isAddToSelectedGroupsDisabled).toBe(false); + expect(comp.allGroupsSelected).toBe(true); + }); + + it('should deselect all groups.', function () { + // select a group + comp.filteredUserGroups[0].checked = true; + + // The function to test + comp.deselectAllUserGroups(); + + //assertions + expect(comp.filteredUserGroups[0].checked).toBe(false); + expect(comp.isAddToSelectedGroupsDisabled).toBe(true); + expect(comp.allGroupsSelected).toBe(false); + }); + + it('should toggle all groups `checked` properties to true.', function () { + //Spy + spyOn(comp, 'selectAllUserGroups').and.callFake(function () { + }); + + comp.allGroupsSelected = true; + + // The function to test + comp.toggleUserGroupsSelectAll(); + + //assertions + expect(comp.selectAllUserGroups).toHaveBeenCalled(); + }); + + it('should toggle all groups `checked` properties to false.', function () { + //Spy + spyOn(comp, 'deselectAllUserGroups').and.callFake(function () { + }); + + comp.allGroupsSelected = false; + + // The function to test + comp.toggleUserGroupsSelectAll(); + + //assertions + expect(comp.deselectAllUserGroups).toHaveBeenCalled(); + }); + + it('should sort `groups` by `column`', function () { + // object to be updated by the test + var column = {name: 'name', label: 'Group Name', sortable: true}; + + // The function to test + comp.sortUserGroups(column); + + //assertions + var filterGroupsCall = comp.filterGroups.calls.mostRecent(); + expect(filterGroupsCall.args[0]).toBe('name'); + expect(filterGroupsCall.args[1]).toBe('ASC'); + }); + + it('should cancel the addition of the user to any group', function () { + // the function to test + comp.cancel(); + + //assertions + expect(comp.dialogRef.close).toHaveBeenCalled(); + }); +}); \ No newline at end of file http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/6f26290d/nifi-registry-core/nifi-registry-web-ui/src/main/webapp/components/administration/users/dialogs/add-user/nf-registry-add-user.html ---------------------------------------------------------------------- diff --git a/nifi-registry-core/nifi-registry-web-ui/src/main/webapp/components/administration/users/dialogs/add-user/nf-registry-add-user.html b/nifi-registry-core/nifi-registry-web-ui/src/main/webapp/components/administration/users/dialogs/add-user/nf-registry-add-user.html new file mode 100644 index 0000000..d7423ac --- /dev/null +++ b/nifi-registry-core/nifi-registry-web-ui/src/main/webapp/components/administration/users/dialogs/add-user/nf-registry-add-user.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-add-user-dialog"> + <div class="pad-bottom-md" fxLayout="row" fxLayoutAlign="space-between center"> + <span class="md-card-title">Add User</span> + <button mat-icon-button (click)="cancel()"> + <mat-icon color="primary">close</mat-icon> + </button> + </div> + <div fxLayout="column" fxLayoutAlign="space-between start" class="pad-bottom-md"> + <div class="pad-bottom-md fill-available-width"> + <mat-input-container floatPlaceholder="always" fxFlex> + <input #newUserInput matInput floatPlaceholder="always" placeholder="Identity/Username"> + </mat-input-container> + </div> + <mat-checkbox [(ngModel)]="keepDialogOpen"> + Keep this dialog open after adding user + </mat-checkbox> + </div> + <div fxLayout="row"> + <span fxFlex></span> + <button (click)="cancel()" color="fds-regular" mat-raised-button + i18n="Cancel creation of new user|A button for cancelling the creation of a new user in the registry.@@nf-admin-workflow-create-bucket-button"> + Cancel + </button> + <button [disabled]="newUserInput.value.length === 0" class="push-left-sm" id="add-new-user-button" (click)="addUser(newUserInput)" color="fds-primary" mat-raised-button + i18n="Add new user button|A button for adding a new user in the registry.@@nf-admin-workflow-add-user-button"> + Add + </button> + </div> +</div> http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/6f26290d/nifi-registry-core/nifi-registry-web-ui/src/main/webapp/components/administration/users/dialogs/add-user/nf-registry-add-user.js ---------------------------------------------------------------------- diff --git a/nifi-registry-core/nifi-registry-web-ui/src/main/webapp/components/administration/users/dialogs/add-user/nf-registry-add-user.js b/nifi-registry-core/nifi-registry-web-ui/src/main/webapp/components/administration/users/dialogs/add-user/nf-registry-add-user.js new file mode 100644 index 0000000..586b7f7 --- /dev/null +++ b/nifi-registry-core/nifi-registry-web-ui/src/main/webapp/components/administration/users/dialogs/add-user/nf-registry-add-user.js @@ -0,0 +1,107 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +var ngCore = require('@angular/core'); +var NfRegistryService = require('nifi-registry/services/nf-registry.service.js'); +var NfRegistryApi = require('nifi-registry/services/nf-registry.api.js'); +var ngMaterial = require('@angular/material'); +var fdsSnackBarsModule = require('@flow-design-system/snackbars'); + +/** + * NfRegistryAddUser constructor. + * + * @param nfRegistryApi The api service. + * @param nfRegistryService The nf-registry.service module. + * @param fdsSnackBarService The FDS snack bar service module. + * @param matDialogRef The angular material dialog ref. + * @constructor + */ +function NfRegistryAddUser(nfRegistryApi, nfRegistryService, fdsSnackBarService, matDialogRef) { + // Services + this.snackBarService = fdsSnackBarService; + this.nfRegistryService = nfRegistryService; + this.nfRegistryApi = nfRegistryApi; + this.dialogRef = matDialogRef; + // local state + this.keepDialogOpen = false; +}; + +NfRegistryAddUser.prototype = { + constructor: NfRegistryAddUser, + + /** + * Create a new user. + * + * @param addUserInput The addUserInput element. + */ + addUser: function (addUserInput) { + var self = this; + this.nfRegistryApi.addUser(addUserInput.value).subscribe(function (user) { + if (!user.error) { + self.nfRegistryService.users.push(user); + self.nfRegistryService.allUsersAndGroupsSelected = false; + self.nfRegistryService.filterUsersAndGroups(); + if (self.keepDialogOpen !== true) { + self.dialogRef.close(); + } + self.snackBarService.openCoaster({ + title: 'Success', + message: 'User has been added.', + verticalPosition: 'bottom', + horizontalPosition: 'right', + icon: 'fa fa-check-circle-o', + color: '#1EB475', + duration: 3000 + }); + } else { + self.dialogRef.close(); + } + }); + }, + + /** + * Cancel creation of a new bucket and close dialog. + */ + cancel: function () { + this.dialogRef.close(); + }, + + /** + * Focus the new user input. + */ + ngAfterViewChecked: function () { + this.newUserInput.nativeElement.focus(); + } +}; + +NfRegistryAddUser.annotations = [ + new ngCore.Component({ + template: require('./nf-registry-add-user.html!text'), + queries: { + newUserInput: new ngCore.ViewChild('newUserInput') + } + }) +]; + +NfRegistryAddUser.parameters = [ + NfRegistryApi, + NfRegistryService, + fdsSnackBarsModule.FdsSnackBarService, + ngMaterial.MatDialogRef +]; + +module.exports = NfRegistryAddUser; http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/6f26290d/nifi-registry-core/nifi-registry-web-ui/src/main/webapp/components/administration/users/dialogs/add-user/nf-registry-add-user.spec.js ---------------------------------------------------------------------- diff --git a/nifi-registry-core/nifi-registry-web-ui/src/main/webapp/components/administration/users/dialogs/add-user/nf-registry-add-user.spec.js b/nifi-registry-core/nifi-registry-web-ui/src/main/webapp/components/administration/users/dialogs/add-user/nf-registry-add-user.spec.js new file mode 100644 index 0000000..17f12f5 --- /dev/null +++ b/nifi-registry-core/nifi-registry-web-ui/src/main/webapp/components/administration/users/dialogs/add-user/nf-registry-add-user.spec.js @@ -0,0 +1,86 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the 'License'); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an 'AS IS' BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +var NfRegistryApi = require('nifi-registry/services/nf-registry.api.js'); +var NfRegistryService = require('nifi-registry/services/nf-registry.service.js'); +var NfRegistryAddUser = require('nifi-registry/components/administration/users/dialogs/add-user/nf-registry-add-user.js'); +var rxjs = require('rxjs/Rx'); + +describe('NfRegistryAddUser Component isolated unit tests', function () { + var comp; + var nfRegistryService; + var nfRegistryApi; + + beforeEach(function () { + nfRegistryService = new NfRegistryService(); + nfRegistryApi = new NfRegistryApi(); + comp = new NfRegistryAddUser(nfRegistryApi, + nfRegistryService, + { + openCoaster: function () { + } + }, + { + close: function () { + } + }); + + // Spy + spyOn(nfRegistryApi, 'addUser').and.callFake(function () { + }).and.returnValue(rxjs.Observable.of([{ + 'identifier': '2e04b4fb-9513-47bb-aa74-1ae34616bfdc', + 'identity': 'New User #1' + }])); + spyOn(nfRegistryService, 'filterUsersAndGroups'); + spyOn(comp.dialogRef, 'close'); + }); + + it('should make a call to the api to create a new user and close the dialog', function () { + // the function to test + comp.addUser({value: 'New User #1'}); + + //assertions + expect(comp).toBeDefined(); + expect(nfRegistryService.users.length).toBe(1); + expect(nfRegistryService.allUsersAndGroupsSelected).toBe(false); + expect(nfRegistryService.filterUsersAndGroups).toHaveBeenCalled(); + expect(comp.dialogRef.close).toHaveBeenCalled(); + }); + + it('should make a call to the api to create a new user and keep the dialog open', function () { + // setup the component + comp.keepDialogOpen = true; + + // the function to test + comp.addUser({value: 'New User #1'}); + + //assertions + expect(comp).toBeDefined(); + expect(nfRegistryService.users.length).toBe(1); + expect(nfRegistryService.allUsersAndGroupsSelected).toBe(false); + expect(nfRegistryService.filterUsersAndGroups).toHaveBeenCalled(); + expect(comp.dialogRef.close.calls.count()).toEqual(0); + }); + + it('should cancel the creation of a new user', function () { + // the function to test + comp.cancel(); + + //assertions + expect(comp.dialogRef.close).toHaveBeenCalled(); + }); +}); \ No newline at end of file http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/6f26290d/nifi-registry-core/nifi-registry-web-ui/src/main/webapp/components/administration/users/dialogs/add-users-to-group/nf-registry-add-users-to-group.html ---------------------------------------------------------------------- diff --git a/nifi-registry-core/nifi-registry-web-ui/src/main/webapp/components/administration/users/dialogs/add-users-to-group/nf-registry-add-users-to-group.html b/nifi-registry-core/nifi-registry-web-ui/src/main/webapp/components/administration/users/dialogs/add-users-to-group/nf-registry-add-users-to-group.html new file mode 100644 index 0000000..6f8670c --- /dev/null +++ b/nifi-registry-core/nifi-registry-web-ui/src/main/webapp/components/administration/users/dialogs/add-users-to-group/nf-registry-add-users-to-group.html @@ -0,0 +1,80 @@ +<!-- +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-add-selected-users-to-group-dialog"> + <div class="pad-bottom-md" fxLayout="row" fxLayoutAlign="space-between center"> + <span class="md-card-title">Add users to group</span> + <button mat-icon-button (click)="cancel()"> + <mat-icon color="primary">close</mat-icon> + </button> + </div> + <div *ngIf="filteredUsers.length > 0" class="pad-bottom-md"> + <div id="nifi-registry-users-administration-list-container-column-header" class="td-data-table"> + <div class="td-data-table-column" (click)="sortUsers(column)" + *ngFor="let column of usersColumns" + fxFlex="{{column.width}}"> + {{column.label}} + <i *ngIf="column.active && column.sortable && column.sortOrder === 'ASC'" class="fa fa-caret-up" + aria-hidden="true"></i> + <i *ngIf="column.active && column.sortable && column.sortOrder === 'DESC'" class="fa fa-caret-down" + aria-hidden="true"></i> + </div> + <div class="td-data-table-column"> + <mat-checkbox [(ngModel)]="allUsersSelected" + (checked)="allUsersSelected" + (change)="toggleUsersSelectAll()"></mat-checkbox> + </div> + </div> + <div id="nifi-registry-add-selected-users-to-group-list-container"> + <div fxLayout="row" fxLayoutAlign="space-between center" + class="td-data-table-row" + [ngClass]="{'selected' : user.checked}" + *ngFor="let user of filteredUsers" + (click)="user.checked = !user.checked;determineAllUsersSelectedState();"> + <div class="td-data-table-cell" *ngFor="let column of usersColumns" + fxFlex="{{column.width}}"> + <div class="ellipsis" matTooltip="{{column.format ? column.format(user[column.name]) : user[column.name]}}"> + {{column.format ? column.format(user[column.name]) : user[column.name]}} + </div> + </div> + <div class="td-data-table-cell"> + <mat-checkbox [(ngModel)]="user.checked" + [checked]="user.checked" + (change)="determineAllUsersSelectedState()" + (click)="user.checked = !user.checked;determineAllUsersSelectedState()"> + </mat-checkbox> + </div> + </div> + </div> + </div> + <div class="mat-padding push-bottom-md" *ngIf="filteredUsers.length === 0" layout="row" + layout-align="center center"> + <h3>All users belong to this group.</h3> + </div> + <div fxLayout="row"> + <span fxFlex></span> + <button (click)="cancel()" color="fds-regular" mat-raised-button + i18n="Cancel addition of selected users to group|A button for cancelling the addition of selected users to a group in the registry.@@nf-admin-workflow-cancel-add-selected-users-to-group-button"> + Cancel + </button> + <button [disabled]="isAddSelectedUsersToGroupDisabled" class="push-left-sm" (click)="addSelectedUsersToGroup()" + color="fds-primary" mat-raised-button + i18n="Add selected users to group button|A button for adding users to an existing group in the registry.@@nf-admin-workflow-add-selected-users-to-group-button"> + Add + </button> + </div> +</div> http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/6f26290d/nifi-registry-core/nifi-registry-web-ui/src/main/webapp/components/administration/users/dialogs/add-users-to-group/nf-registry-add-users-to-group.js ---------------------------------------------------------------------- diff --git a/nifi-registry-core/nifi-registry-web-ui/src/main/webapp/components/administration/users/dialogs/add-users-to-group/nf-registry-add-users-to-group.js b/nifi-registry-core/nifi-registry-web-ui/src/main/webapp/components/administration/users/dialogs/add-users-to-group/nf-registry-add-users-to-group.js new file mode 100644 index 0000000..fff468b --- /dev/null +++ b/nifi-registry-core/nifi-registry-web-ui/src/main/webapp/components/administration/users/dialogs/add-users-to-group/nf-registry-add-users-to-group.js @@ -0,0 +1,247 @@ +/* + * 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 covalentCore = require('@covalent/core'); +var NfRegistryApi = require('nifi-registry/services/nf-registry.api.js'); +var ngCore = require('@angular/core'); +var fdsSnackBarsModule = require('@flow-design-system/snackbars'); +var NfRegistryService = require('nifi-registry/services/nf-registry.service.js'); +var ngMaterial = require('@angular/material'); +var $ = require('jquery'); + +/** + * NfRegistryAddUsersToGroup constructor. + * + * @param nfRegistryApi The api service. + * @param tdDataTableService The covalent data table service module. + * @param nfRegistryService The nf-registry.service module. + * @param matDialogRef The angular material dialog ref. + * @param fdsSnackBarService The FDS snack bar service module. + * @param data The data passed into this component. + * @constructor + */ +function NfRegistryAddUsersToGroup(nfRegistryApi, tdDataTableService, nfRegistryService, matDialogRef, fdsSnackBarService, data) { + // Services + this.dataTableService = tdDataTableService; + this.snackBarService = fdsSnackBarService; + this.nfRegistryService = nfRegistryService; + this.nfRegistryApi = nfRegistryApi; + this.dialogRef = matDialogRef; + this.data = data; + + // local state + //make an independent copy of the users for sorting and selecting within the scope of this component + this.users = $.extend(true, [], this.nfRegistryService.users); + this.filteredUsers = []; + this.isAddSelectedUsersToGroupDisabled = true; + this.usersSearchTerms = []; + this.allUsersSelected = false; + this.usersColumns = [ + { + name: 'identity', + label: 'Display Name', + sortable: true, + tooltip: 'Group name.', + width: 100 + } + ]; +}; + +NfRegistryAddUsersToGroup.prototype = { + constructor: NfRegistryAddUsersToGroup, + + /** + * Initialize the component. + */ + ngOnInit: function () { + var self = this; + + this.data.group.users.forEach(function (groupUser) { + self.users = self.users.filter(function (user) { + return (user.identifier !== groupUser.identifier) ? true : false + }); + }); + + this.filterUsers(); + this.deselectAllUsers(); + this.determineAllUsersSelectedState(); + }, + + /** + * Filter users. + * + * @param {string} [sortBy] The column name to sort `usersColumns` by. + * @param {string} [sortOrder] The order. Either 'ASC' or 'DES' + */ + filterUsers: function (sortBy, sortOrder) { + // if `sortOrder` is `undefined` then use 'ASC' + if (sortOrder === undefined) { + sortOrder = 'ASC' + } + // if `sortBy` is `undefined` then find the first sortable column in `dropletColumns` + if (sortBy === undefined) { + var arrayLength = this.usersColumns.length; + for (var i = 0; i < arrayLength; i++) { + if (this.usersColumns[i].sortable === true) { + sortBy = this.usersColumns[i].name; + //only one column can be actively sorted so we reset all to inactive + this.usersColumns.forEach(function (c) { + c.active = false; + }); + //and set this column as the actively sorted column + this.usersColumns[i].active = true; + this.usersColumns[i].sortOrder = sortOrder; + break; + } + } + } + + var newUsersData = this.users; + + for (var i = 0; i < this.usersSearchTerms.length; i++) { + newUsersData = this.dataTableService.filterData(newUsersData, this.usersSearchTerms[i], true); + } + + newUsersData = this.dataTableService.sortData(newUsersData, sortBy, sortOrder); + this.filteredUsers = newUsersData; + }, + + /** + * Sort `filteredUsers` by `column`. + * + * @param column The column to sort by. + */ + sortUsers: function (column) { + if (column.sortable) { + var sortBy = column.name; + var sortOrder = column.sortOrder = (column.sortOrder === 'ASC') ? 'DESC' : 'ASC'; + this.filterUsers(sortBy, sortOrder); + } + }, + + /** + * Checks the `allUsersSelected` property state and either selects + * or deselects each of the `filteredUsers`. + */ + toggleUsersSelectAll: function () { + if (this.allUsersSelected) { + this.selectAllUsers(); + } else { + this.deselectAllUsers(); + } + }, + + /** + * Sets the `checked` property of each of the `filteredUsers` to true + * and sets the `isAddSelectedUsersToGroupDisabled` and the `allUsersSelected` + * properties accordingly. + */ + selectAllUsers: function () { + this.filteredUsers.forEach(function (c) { + c.checked = true; + }); + this.isAddSelectedUsersToGroupDisabled = false; + this.allUsersSelected = true; + }, + + /** + * Sets the `checked` property of each group to false + * and sets the `isAddSelectedUsersToGroupDisabled` and the `allUsersSelected` + * properties accordingly. + */ + deselectAllUsers: function () { + this.filteredUsers.forEach(function (c) { + c.checked = false; + }); + this.isAddSelectedUsersToGroupDisabled = true; + this.allUsersSelected = false; + }, + + /** + * Checks of each of the `filteredUsers`'s checked property state + * and sets the `allBucketsSelected` and `isAddSelectedUsersToGroupDisabled` + * property accordingly. + */ + determineAllUsersSelectedState: function () { + var selected = 0; + var allSelected = true; + this.filteredUsers.forEach(function (c) { + if (c.checked) { + selected++; + } + if (c.checked === undefined || c.checked === false) { + allSelected = false; + } + }); + + if (selected > 0) { + this.isAddSelectedUsersToGroupDisabled = false; + } else { + this.isAddSelectedUsersToGroupDisabled = true; + } + + this.allUsersSelected = allSelected; + }, + + /** + * Adds each of the selected users to this group. + */ + addSelectedUsersToGroup: function () { + var self = this; + this.filteredUsers.filter(function (filteredUser) { + if(filteredUser.checked) { + self.data.group.users.push(filteredUser); + } + }); + this.nfRegistryApi.updateUserGroup(self.data.group.identifier, self.data.group.identity, self.data.group.users).subscribe(function (group) { + self.dialogRef.close(); + var snackBarRef = self.snackBarService.openCoaster({ + title: 'Success', + message: 'Selected users have been added to the ' + self.data.group.identity + ' group.', + verticalPosition: 'bottom', + horizontalPosition: 'right', + icon: 'fa fa-check-circle-o', + color: '#1EB475', + duration: 3000 + }); + }); + }, + + /** + * Cancel adding selected users to groups and close the dialog. + */ + cancel: function () { + this.dialogRef.close(); + } +}; + +NfRegistryAddUsersToGroup.annotations = [ + new ngCore.Component({ + template: require('./nf-registry-add-users-to-group.html!text') + }) +]; + +NfRegistryAddUsersToGroup.parameters = [ + NfRegistryApi, + covalentCore.TdDataTableService, + NfRegistryService, + ngMaterial.MatDialogRef, + fdsSnackBarsModule.FdsSnackBarService, + ngMaterial.MAT_DIALOG_DATA +]; + +module.exports = NfRegistryAddUsersToGroup; http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/6f26290d/nifi-registry-core/nifi-registry-web-ui/src/main/webapp/components/administration/users/dialogs/add-users-to-group/nf-registry-add-users-to-group.spec.js ---------------------------------------------------------------------- diff --git a/nifi-registry-core/nifi-registry-web-ui/src/main/webapp/components/administration/users/dialogs/add-users-to-group/nf-registry-add-users-to-group.spec.js b/nifi-registry-core/nifi-registry-web-ui/src/main/webapp/components/administration/users/dialogs/add-users-to-group/nf-registry-add-users-to-group.spec.js new file mode 100644 index 0000000..c1d2c71 --- /dev/null +++ b/nifi-registry-core/nifi-registry-web-ui/src/main/webapp/components/administration/users/dialogs/add-users-to-group/nf-registry-add-users-to-group.spec.js @@ -0,0 +1,170 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the 'License'); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an 'AS IS' BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +var NfRegistryApi = require('nifi-registry/services/nf-registry.api.js'); +var NfRegistryService = require('nifi-registry/services/nf-registry.service.js'); +var NfRegistryAddUsersToGroup = require('nifi-registry/components/administration/users/dialogs/add-users-to-group/nf-registry-add-users-to-group.js'); +var rxjs = require('rxjs/Rx'); +var covalentCore = require('@covalent/core'); +var fdsSnackBarsModule = require('@flow-design-system/snackbars'); + +describe('NfRegistryAddUsersToGroup Component isolated unit tests', function () { + var comp; + var nfRegistryService; + var nfRegistryApi; + var snackBarService; + var dataTableService; + + beforeEach(function () { + nfRegistryService = new NfRegistryService(); + // setup the nfRegistryService + nfRegistryService.group = {identifier: 1, identity: 'Group 1', users: []}; + nfRegistryService.users = [{identifier: 2, identity: 'User 1', checked: true}]; + + nfRegistryApi = new NfRegistryApi(); + snackBarService = new fdsSnackBarsModule.FdsSnackBarService(); + dataTableService = new covalentCore.TdDataTableService(); + comp = new NfRegistryAddUsersToGroup(nfRegistryApi, dataTableService, nfRegistryService, { + close: function () { + } + }, snackBarService, {group: nfRegistryService.group}); + + // Spy + spyOn(nfRegistryApi, 'updateUserGroup').and.callFake(function () { + }).and.returnValue(rxjs.Observable.of({identifier: 1, identity: 'Group 1'})); + spyOn(comp.dialogRef, 'close'); + spyOn(comp.snackBarService, 'openCoaster'); + spyOn(comp, 'filterUsers').and.callThrough(); + + // initialize the component + comp.ngOnInit(); + + //assertions + expect(comp.filterUsers).toHaveBeenCalled(); + expect(comp.filteredUsers[0].identity).toEqual('User 1'); + expect(comp.filteredUsers.length).toBe(1); + expect(comp).toBeDefined(); + }); + + it('should make a call to the api to add selected users to the group', function () { + // select a group + comp.filteredUsers[0].checked = true; + + // the function to test + comp.addSelectedUsersToGroup(); + + //assertions + expect(comp.dialogRef.close).toHaveBeenCalled(); + expect(comp.snackBarService.openCoaster).toHaveBeenCalled(); + }); + + it('should determine if all users are selected', function () { + // select a group + comp.filteredUsers[0].checked = true; + + // the function to test + comp.determineAllUsersSelectedState(); + + //assertions + expect(comp.allUsersSelected).toBe(true); + expect(comp.isAddSelectedUsersToGroupDisabled).toBe(false); + }); + + it('should determine all user groups are not selected', function () { + // select a group + comp.filteredUsers[0].checked = false; + + // the function to test + comp.determineAllUsersSelectedState(); + + //assertions + expect(comp.allUsersSelected).toBe(false); + expect(comp.isAddSelectedUsersToGroupDisabled).toBe(true); + }); + + it('should select all groups.', function () { + // The function to test + comp.selectAllUsers(); + + //assertions + expect(comp.filteredUsers[0].checked).toBe(true); + expect(comp.isAddSelectedUsersToGroupDisabled).toBe(false); + expect(comp.allUsersSelected).toBe(true); + }); + + it('should deselect all groups.', function () { + // select a group + comp.filteredUsers[0].checked = true; + + // The function to test + comp.deselectAllUsers(); + + //assertions + expect(comp.filteredUsers[0].checked).toBe(false); + expect(comp.isAddSelectedUsersToGroupDisabled).toBe(true); + expect(comp.allUsersSelected).toBe(false); + }); + + it('should toggle all groups `checked` properties to true.', function () { + //Spy + spyOn(comp, 'selectAllUsers').and.callFake(function () { + }); + + comp.allUsersSelected = true; + + // The function to test + comp.toggleUsersSelectAll(); + + //assertions + expect(comp.selectAllUsers).toHaveBeenCalled(); + }); + + it('should toggle all groups `checked` properties to false.', function () { + //Spy + spyOn(comp, 'deselectAllUsers').and.callFake(function () { + }); + + comp.allUsersSelected = false; + + // The function to test + comp.toggleUsersSelectAll(); + + //assertions + expect(comp.deselectAllUsers).toHaveBeenCalled(); + }); + + it('should sort `groups` by `column`', function () { + // object to be updated by the test + var column = {name: 'name', label: 'Group Name', sortable: true}; + + // The function to test + comp.sortUsers(column); + + //assertions + var filterUsersCall = comp.filterUsers.calls.mostRecent(); + expect(filterUsersCall.args[0]).toBe('name'); + expect(filterUsersCall.args[1]).toBe('ASC'); + }); + + it('should cancel the creation of a new user', function () { + // the function to test + comp.cancel(); + + //assertions + expect(comp.dialogRef.close).toHaveBeenCalled(); + }); +}); \ No newline at end of file http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/6f26290d/nifi-registry-core/nifi-registry-web-ui/src/main/webapp/components/administration/users/dialogs/create-new-group/nf-registry-create-new-group.html ---------------------------------------------------------------------- diff --git a/nifi-registry-core/nifi-registry-web-ui/src/main/webapp/components/administration/users/dialogs/create-new-group/nf-registry-create-new-group.html b/nifi-registry-core/nifi-registry-web-ui/src/main/webapp/components/administration/users/dialogs/create-new-group/nf-registry-create-new-group.html new file mode 100644 index 0000000..d153651 --- /dev/null +++ b/nifi-registry-core/nifi-registry-web-ui/src/main/webapp/components/administration/users/dialogs/create-new-group/nf-registry-create-new-group.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-new-group-dialog"> + <div class="pad-bottom-md" fxLayout="row" fxLayoutAlign="space-between center"> + <span class="md-card-title">Create New Group</span> + <button mat-icon-button (click)="cancel()"> + <mat-icon color="primary">close</mat-icon> + </button> + </div> + <div fxLayout="column" fxLayoutAlign="space-between start" class="pad-bottom-md"> + <div class="pad-bottom-md fill-available-width"> + <mat-input-container floatPlaceholder="always" fxFlex> + <input #createNewGroupInput matInput floatPlaceholder="always" placeholder="Display Name"> + </mat-input-container> + </div> + <mat-checkbox [(ngModel)]="keepDialogOpen"> + Keep this dialog open after creating group + </mat-checkbox> + </div> + <div fxLayout="row"> + <span fxFlex></span> + <button (click)="cancel()" color="fds-regular" mat-raised-button + i18n="Cancel creation of new group|A button for cancelling the creation of a new group in the registry.@@nf-admin-workflow-cancel-create-new-group-button"> + Cancel + </button> + <button [disabled]="createNewGroupInput.value.length === 0" class="push-left-sm" (click)="createNewGroup(createNewGroupInput)" color="fds-primary" mat-raised-button + i18n="Create new group button|A button for creating a new group in the registry.@@nf-admin-workflow-create-new-group-button"> + Create + </button> + </div> +</div> http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/6f26290d/nifi-registry-core/nifi-registry-web-ui/src/main/webapp/components/administration/users/dialogs/create-new-group/nf-registry-create-new-group.js ---------------------------------------------------------------------- diff --git a/nifi-registry-core/nifi-registry-web-ui/src/main/webapp/components/administration/users/dialogs/create-new-group/nf-registry-create-new-group.js b/nifi-registry-core/nifi-registry-web-ui/src/main/webapp/components/administration/users/dialogs/create-new-group/nf-registry-create-new-group.js new file mode 100644 index 0000000..bf8075e --- /dev/null +++ b/nifi-registry-core/nifi-registry-web-ui/src/main/webapp/components/administration/users/dialogs/create-new-group/nf-registry-create-new-group.js @@ -0,0 +1,108 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +var ngCore = require('@angular/core'); +var NfRegistryService = require('nifi-registry/services/nf-registry.service.js'); +var NfRegistryApi = require('nifi-registry/services/nf-registry.api.js'); +var ngMaterial = require('@angular/material'); +var fdsSnackBarsModule = require('@flow-design-system/snackbars'); + +/** + * NfRegistryCreateNewGroup constructor. + * + * @param nfRegistryApi The api service. + * @param fdsSnackBarService The FDS snack bar service module. + * @param nfRegistryService The nf-registry.service module. + * @param matDialogRef The angular material dialog ref. + * @constructor + */ +function NfRegistryCreateNewGroup(nfRegistryApi, fdsSnackBarService, nfRegistryService, matDialogRef) { + // Services + this.snackBarService = fdsSnackBarService; + this.nfRegistryService = nfRegistryService; + this.nfRegistryApi = nfRegistryApi; + this.dialogRef = matDialogRef; + // local state + this.keepDialogOpen = false; +}; + +NfRegistryCreateNewGroup.prototype = { + constructor: NfRegistryCreateNewGroup, + + /** + * Create a new group. + * + * @param createNewGroupInput The createNewGroupInput element. + */ + createNewGroup: function (createNewGroupInput) { + var self = this; + // create new group with any selected users added to the new group + this.nfRegistryApi.createNewGroup(null, createNewGroupInput.value, this.nfRegistryService.getSelectedUsers()).subscribe(function (group) { + if (!group.error) { + self.nfRegistryService.groups.push(group); + self.nfRegistryService.filterUsersAndGroups(); + self.nfRegistryService.allUsersAndGroupsSelected = false; + if (self.keepDialogOpen !== true) { + self.dialogRef.close(); + } + self.snackBarService.openCoaster({ + title: 'Success', + message: 'Group has been added.', + verticalPosition: 'bottom', + horizontalPosition: 'right', + icon: 'fa fa-check-circle-o', + color: '#1EB475', + duration: 3000 + }); + } else { + self.dialogRef.close(); + } + }); + }, + + /** + * Cancel creation of a new bucket and close dialog. + */ + cancel: function () { + this.dialogRef.close(); + }, + + /** + * Focus the new group input. + */ + ngAfterViewChecked: function () { + this.createNewGroupInput.nativeElement.focus(); + } +}; + +NfRegistryCreateNewGroup.annotations = [ + new ngCore.Component({ + template: require('./nf-registry-create-new-group.html!text'), + queries: { + createNewGroupInput: new ngCore.ViewChild('createNewGroupInput') + } + }) +]; + +NfRegistryCreateNewGroup.parameters = [ + NfRegistryApi, + fdsSnackBarsModule.FdsSnackBarService, + NfRegistryService, + ngMaterial.MatDialogRef +]; + +module.exports = NfRegistryCreateNewGroup; http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/6f26290d/nifi-registry-core/nifi-registry-web-ui/src/main/webapp/components/administration/users/dialogs/create-new-group/nf-registry-create-new-group.spec.js ---------------------------------------------------------------------- diff --git a/nifi-registry-core/nifi-registry-web-ui/src/main/webapp/components/administration/users/dialogs/create-new-group/nf-registry-create-new-group.spec.js b/nifi-registry-core/nifi-registry-web-ui/src/main/webapp/components/administration/users/dialogs/create-new-group/nf-registry-create-new-group.spec.js new file mode 100644 index 0000000..631e415 --- /dev/null +++ b/nifi-registry-core/nifi-registry-web-ui/src/main/webapp/components/administration/users/dialogs/create-new-group/nf-registry-create-new-group.spec.js @@ -0,0 +1,85 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the 'License'); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an 'AS IS' BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +var NfRegistryApi = require('nifi-registry/services/nf-registry.api.js'); +var NfRegistryService = require('nifi-registry/services/nf-registry.service.js'); +var NfRegistryCreateNewGroup = require('nifi-registry/components/administration/users/dialogs/create-new-group/nf-registry-create-new-group.js'); +var rxjs = require('rxjs/Rx'); + +describe('NfRegistryCreateNewGroup Component isolated unit tests', function () { + var comp; + var nfRegistryService; + var nfRegistryApi; + + beforeEach(function () { + nfRegistryService = new NfRegistryService(); + nfRegistryApi = new NfRegistryApi(); + comp = new NfRegistryCreateNewGroup(nfRegistryApi, { + openCoaster: function () { + } + }, + nfRegistryService, + { + close: function () { + } + }); + + // Spy + spyOn(nfRegistryApi, 'createNewGroup').and.callFake(function () { + }).and.returnValue(rxjs.Observable.of([{ + 'identifier': '2e04b4fb-9513-47bb-aa74-1ae34616bfdc', + 'identity': 'New Group #1' + }])); + spyOn(nfRegistryService, 'filterUsersAndGroups'); + spyOn(comp.dialogRef, 'close'); + }); + + it('should make a call to the api to create a new group and close the dialog.', function () { + // the function to test + comp.createNewGroup({value: 'New Group #1'}); + + //assertions + expect(comp).toBeDefined(); + expect(nfRegistryService.groups.length).toBe(1); + expect(nfRegistryService.allUsersAndGroupsSelected).toBe(false); + expect(nfRegistryService.filterUsersAndGroups).toHaveBeenCalled(); + expect(comp.dialogRef.close).toHaveBeenCalled(); + }); + + it('should make a call to the api to create a new group and keep the dialog open.', function () { + // setup the component + comp.keepDialogOpen = true; + + // the function to test + comp.createNewGroup({value: 'New Group #1'}); + + //assertions + expect(comp).toBeDefined(); + expect(nfRegistryService.groups.length).toBe(1); + expect(nfRegistryService.allUsersAndGroupsSelected).toBe(false); + expect(nfRegistryService.filterUsersAndGroups).toHaveBeenCalled(); + expect(comp.dialogRef.close.calls.count()).toEqual(0); + }); + + it('should cancel the creation of a new group', function () { + // the function to test + comp.cancel(); + + //assertions + expect(comp.dialogRef.close).toHaveBeenCalled(); + }); +}); \ No newline at end of file