diff options
author | Christopher Lott (Christopher) (cl778h) <clott@vm-ep-dev2.client.research.att.com> | 2017-06-12 09:49:00 -0400 |
---|---|---|
committer | Christopher Lott (cl778h) <clott@research.att.com> | 2017-06-12 13:42:43 -0400 |
commit | 627badaf69987c01811c477219fd943757a635f5 (patch) | |
tree | 97df9449a411d1ecf830cc76d8afd6f9b5677bda /ecomp-portal-FE-common/client/app/views/users | |
parent | ba838f2e13f1e8050c75e68bd3733d56d8f416d5 (diff) |
[PORTAL-16 PORTAL-18] Widget ms; staging
Remove staging repositories from poms.
Add widget microservice code base.
Add portal unit tests.
Repair defects.
Normalize line endings.
Change-Id: Ia5e48da2a3141b352439ecd548cddf918f4df585
Signed-off-by: Christopher Lott (cl778h) <clott@research.att.com>
Diffstat (limited to 'ecomp-portal-FE-common/client/app/views/users')
11 files changed, 1837 insertions, 1818 deletions
diff --git a/ecomp-portal-FE-common/client/app/views/users/new-user-dialogs/bulk-user.ack.html b/ecomp-portal-FE-common/client/app/views/users/new-user-dialogs/bulk-user.ack.html index 9527c750..e3bcf0a4 100644 --- a/ecomp-portal-FE-common/client/app/views/users/new-user-dialogs/bulk-user.ack.html +++ b/ecomp-portal-FE-common/client/app/views/users/new-user-dialogs/bulk-user.ack.html @@ -1,32 +1,32 @@ -<!--
- ================================================================================
- ECOMP Portal
- ================================================================================
- Copyright (C) 2017 AT&T Intellectual Property
- ================================================================================
- Licensed 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 class="new-user-modal">
- <div class="search-users-directive">
- <div class="title">Bulk User Upload Acknowledgement</div>
- <div class="main">
- <h1>The valid entries have been uploaded.</h1>
-
- <div class="dialog-control">
- <div id="search-user-cancel-button" class="cancel-button"
- ng-click="closeDialog()">OK</div>
- </div>
- </div>
- </div>
-</div>
+<!-- + ================================================================================ + ECOMP Portal + ================================================================================ + Copyright (C) 2017 AT&T Intellectual Property + ================================================================================ + Licensed 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 class="new-user-modal"> + <div class="search-users-directive"> + <div class="title">Bulk User Upload Acknowledgement</div> + <div class="main"> + <h1>The valid entries have been uploaded.</h1> + + <div class="dialog-control"> + <div id="search-user-cancel-button" class="cancel-button" + ng-click="closeDialog()">OK</div> + </div> + </div> + </div> +</div> diff --git a/ecomp-portal-FE-common/client/app/views/users/new-user-dialogs/bulk-user.confirm.html b/ecomp-portal-FE-common/client/app/views/users/new-user-dialogs/bulk-user.confirm.html index a3c0b534..6df7d240 100644 --- a/ecomp-portal-FE-common/client/app/views/users/new-user-dialogs/bulk-user.confirm.html +++ b/ecomp-portal-FE-common/client/app/views/users/new-user-dialogs/bulk-user.confirm.html @@ -1,83 +1,83 @@ -<!--
- ================================================================================
- ECOMP Portal
- ================================================================================
- Copyright (C) 2017 AT&T Intellectual Property
- ================================================================================
- Licensed 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 class="bulk-user-modal">
- <div class="title">Bulk User Upload Confirmation</div>
- <div class="main">
-
- <!-- progress indicator -->
- <div class="upload-instructions"
- ng-show="isProcessing">
- {{progressMsg}}
- <br>
- <br>
- <span class="ecomp-spinner"></span>
- </div>
-
- <div ng-hide="isProcessing">
- <div class="upload-instructions">
- Click OK to upload the valid requests.
- Invalid requests will be ignored.</div>
- <div class="c-ecomp-portal-abs-table default"
- style="height: 250px !important">
- <table b2b-table table-data="uploadFile"
- search-string="bulkUser.searchString"
- view-per-page="bulkUser.viewPerPageIgnored"
- current-page="bulkUser.currentPageIgnored"
- total-page="bulkUser.totalPageIgnored">
- <thead b2b-table-row type="header">
- <tr>
- <th id="th-line" b2b-table-header sortable="false">Line</th>
- <th id="th-orgUserId" b2b-table-header sortable="false">Org User ID
- </th>
- <th id="th-approle" b2b-table-header sortable="false">App
- Role</th>
- <th id="th-status" b2b-table-header sortable="false">Status</th>
- </tr>
- </thead>
- <!-- Use track-by="UNIQUE KEY HERE" or leave out if no unique keys in data -->
- <tbody b2b-table-row type="body" class="table-body"
- row-repeat="rowData in uploadFile">
- <tr id="tr-rowData">
- <td class="td-first" b2b-table-body>
- <div ng-bind="rowData.line"></div>
- </td>
- <td b2b-table-body>
- <div ng-bind="rowData.orgUserId"></div>
- </td>
- <td b2b-table-body>
- <div ng-bind="rowData.role"></div>
- </td>
- <td b2b-table-body>
- <div ng-bind="rowData.status"></div>
- </td>
- </tr>
- </tbody>
- </table>
- </div>
-
- </div>
- <div class="dialog-control">
- <button id="bulk-user-ok-button" class="btn btn-alt btn-small" ng-class="{disabled: isValidating}"
- ng-click="updateDB()">Ok</button>
- <button id="bulk-user-cancel-button" class="btn btn-alt btn-small" ng-click="cancelUpload()">Cancel</button>
-
- </div>
- </div>
-</div>
+<!-- + ================================================================================ + ECOMP Portal + ================================================================================ + Copyright (C) 2017 AT&T Intellectual Property + ================================================================================ + Licensed 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 class="bulk-user-modal"> + <div class="title">Bulk User Upload Confirmation</div> + <div class="main"> + + <!-- progress indicator --> + <div class="upload-instructions" + ng-show="isProcessing"> + {{progressMsg}} + <br> + <br> + <span class="ecomp-spinner"></span> + </div> + + <div ng-hide="isProcessing"> + <div class="upload-instructions"> + Click OK to upload the valid requests. + Invalid requests will be ignored.</div> + <div class="c-ecomp-portal-abs-table default" + style="height: 250px !important"> + <table b2b-table table-data="uploadFile" + search-string="bulkUser.searchString" + view-per-page="bulkUser.viewPerPageIgnored" + current-page="bulkUser.currentPageIgnored" + total-page="bulkUser.totalPageIgnored"> + <thead b2b-table-row type="header"> + <tr> + <th id="th-line" b2b-table-header sortable="false">Line</th> + <th id="th-orgUserId" b2b-table-header sortable="false">Org User ID + </th> + <th id="th-approle" b2b-table-header sortable="false">App + Role</th> + <th id="th-status" b2b-table-header sortable="false">Status</th> + </tr> + </thead> + <!-- Use track-by="UNIQUE KEY HERE" or leave out if no unique keys in data --> + <tbody b2b-table-row type="body" class="table-body" + row-repeat="rowData in uploadFile"> + <tr id="tr-rowData"> + <td class="td-first" b2b-table-body> + <div ng-bind="rowData.line"></div> + </td> + <td b2b-table-body> + <div ng-bind="rowData.orgUserId"></div> + </td> + <td b2b-table-body> + <div ng-bind="rowData.role"></div> + </td> + <td b2b-table-body> + <div ng-bind="rowData.status"></div> + </td> + </tr> + </tbody> + </table> + </div> + + </div> + <div class="dialog-control"> + <button id="bulk-user-ok-button" class="btn btn-alt btn-small" ng-class="{disabled: isValidating}" + ng-click="updateDB()">Ok</button> + <button id="bulk-user-cancel-button" class="btn btn-alt btn-small" ng-click="cancelUpload()">Cancel</button> + + </div> + </div> +</div> diff --git a/ecomp-portal-FE-common/client/app/views/users/new-user-dialogs/bulk-user.controller.js b/ecomp-portal-FE-common/client/app/views/users/new-user-dialogs/bulk-user.controller.js index e3046b86..e73fe290 100644 --- a/ecomp-portal-FE-common/client/app/views/users/new-user-dialogs/bulk-user.controller.js +++ b/ecomp-portal-FE-common/client/app/views/users/new-user-dialogs/bulk-user.controller.js @@ -1,577 +1,577 @@ -/*-
- * ================================================================================
- * ECOMP Portal
- * ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property
- * ================================================================================
- * Licensed 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.
- * ================================================================================
- */
-/**
- * bulk user upload controller
- */
-'use strict';
-(function () {
- class BulkUserModalCtrl {
- constructor($scope, $log, $filter, $q, usersService, applicationsService, confirmBoxService, functionalMenuService, ngDialog) {
-
- // Set to true for copious console output
- var debug = false;
- // Roles fetched from app service
- var appRolesResult = [];
- // Users fetched from user service
- var userCheckResult = [];
- // Requests for user-role assignment built by validator
- var appUserRolesRequest = [];
-
- let init = () => {
- if (debug)
- $log.debug('BulkUserModalCtrl::init');
- // Angular insists on this.
- $scope.fileModel = {};
- // Model for drop-down
- $scope.adminApps = [];
- // Enable modal controls
- this.step1 = true;
- this.fileSelected = false;
-
- // Flag that indicates background work is proceeding
- $scope.isProcessing = true;
-
- // Load user's admin applications
- applicationsService.getAdminApps().promise().then(apps => {
- if (debug)
- $log.debug('BulkUserModalCtrl::init: getAdminApps returned' + JSON.stringify(apps));
- if (!apps || typeof(apps) != 'object') {
- $log.error('BulkUserModalCtrl::init: getAdminApps returned unexpected data');
- }
- else {
- if (debug)
- $log.debug('BulkUserModalCtrl::init: admin apps length is ', apps.length);
-
- // Sort app names and populate the drop-down model
- let sortedApps = apps.sort(getSortOrder('name', true));
- for (let i = 0; i < sortedApps.length; ++i) {
- $scope.adminApps.push({
- index: i,
- id: sortedApps[i].id,
- value: sortedApps[i].name,
- title: sortedApps[i].name
- });
- }
- // Pick the first one in the list
- $scope.selectedApplication = $scope.adminApps[0];
- }
- $scope.isProcessing = false;
- }).catch(err => {
- $log.error('BulkUserModalCtrl::init: getAdminApps threw', err);
- $scope.isProcessing = false;
- });
-
- }; // init
-
- // Answers a function that compares properties with the specified name.
- let getSortOrder = (prop, foldCase) => {
- return function(a, b) {
- let aProp = foldCase ? a[prop].toLowerCase() : a[prop];
- let bProp = foldCase ? b[prop].toLowerCase() : b[prop];
- if (aProp > bProp)
- return 1;
- else if (aProp < bProp)
- return -1;
- else
- return 0;
- }
- }
-
- //This is a fix for dropdown selection, due to b2b dropdown only update value field
- $scope.$watch('selectedApplication.value', (newVal, oldVal) => {
- for(var i=0;i<$scope.adminApps.length;i++){
- if($scope.adminApps[i].value==newVal){
- $scope.selectedApplication=angular.copy($scope.adminApps[i]);;
- }
- }
- });
-
- // Invoked when user picks an app on the drop-down.
- $scope.appSelected = () => {
- if (debug)
- $log.debug('BulkUserModalCtrl::appSelected: selectedApplication.id is ' + $scope.selectedApplication.id);
- this.appSelected = true;
- }
-
- // Caches the file name supplied by the event handler.
- $scope.fileChangeHandler = (event, files) => {
- this.fileSelected = true;
- this.fileToRead = files[0];
- if (debug)
- $log.debug("BulkUserModalCtrl::fileChangeHandler: file is ", this.fileToRead);
- }; // file change handler
-
- /**
- * Reads the contents of the file, calls portal endpoints
- * to validate roles, userIds and existing role assignments;
- * ultimately builds array of requests to be sent.
- * Creates scope variable with input file contents for
- * communication with functions.
- *
- * This function performs a synchronous step-by-step process
- * using asynchronous promises. The code could all be inline
- * here but the nesting becomes unwieldy.
- */
- $scope.readValidateFile = () => {
- $scope.isProcessing = true;
- $scope.progressMsg = 'Reading upload file..';
- var reader = new FileReader();
- reader.onload = function(event) {
- $scope.uploadFile = $filter('csvToObj')(reader.result);
- if (debug)
- $log.debug('BulkUserModalCtrl::readValidateFile onload: data length is ' + $scope.uploadFile.length);
- // sort input by orgUserId
- $scope.uploadFile.sort(getSortOrder('orgUserId', true));
-
- let appid = $scope.selectedApplication.id;
- $scope.progressMsg = 'Fetching application roles..';
- functionalMenuService.getManagedRolesMenu(appid).then(function (rolesObj) {
- if (debug)
- $log.debug("BulkUserModalCtrl::readValidateFile: managedRolesMenu returned " + JSON.stringify(rolesObj));
- appRolesResult = rolesObj;
- $scope.progressMsg = 'Validating application roles..';
- $scope.verifyRoles();
-
- let userPromises = $scope.buildUserChecks();
- if (debug)
- $log.debug('BulkUserModalCtrl::readValidateFile: userPromises length is ' + userPromises.length);
- $scope.progressMsg = 'Validating Org Users..';
- $q.all(userPromises).then(function() {
- if (debug)
- $log.debug('BulkUserModalCtrl::readValidateFile: userCheckResult length is ' + userCheckResult.length);
- $scope.evalUserCheckResults();
-
- let appPromises = $scope.buildAppRoleChecks();
- if (debug)
- $log.debug('BulkUserModalCtrl::readValidateFile: appPromises length is ' + appPromises.length);
- $scope.progressMsg = 'Querying application for user roles..';
- $q.all(appPromises).then( function() {
- if (debug)
- $log.debug('BulkUserModalCtrl::readValidateFile: appUserRolesRequest length is ' + appUserRolesRequest.length);
- $scope.evalAppRoleCheckResults();
-
- // Re sort by line for the confirmation dialog
- $scope.uploadFile.sort(getSortOrder('line', false));
- // We're done, confirm box may show the table
- if (debug)
- $log.debug('BulkUserModalCtrl::readValidateFile inner-then ends');
- $scope.progressMsg = 'Done.';
- $scope.isProcessing = false;
- },
- function(error) {
- $log.error('BulkUserModalCtrl::readValidateFile: failed retrieving user-app roles');
- $scope.isProcessing = false;
- }
- ); // then of app promises
- },
- function(error) {
- $log.error('BulkUserModalCtrl::readValidateFile: failed retrieving user info');
- $scope.isProcessing = false;
- }
- ); // then of user promises
- },
- function(error) {
- $log.error('BulkUserModalCtrl::readValidateFile: failed retrieving app role info');
- $scope.isProcessing = false;
- }
- ); // then of role promise
-
- } // onload
-
- // Invoke the reader on the selected file
- reader.readAsText(this.fileToRead);
- };
-
- /**
- * Evaluates the result set returned by the app role service.
- * Sets an uploadFile array element status if a role is not defined.
- * Reads and writes scope variable uploadFile.
- * Reads closure variable appRolesResult.
- */
- $scope.verifyRoles = () => {
- if (debug)
- $log.debug('BulkUserModalCtrl::verifyRoles: appRoles is ' + JSON.stringify(appRolesResult));
- // check roles in upload file against defined app roles
- $scope.uploadFile.forEach( function (uploadRow) {
- // skip rows that already have a defined status: headers etc.
- if (uploadRow.status) {
- if (debug)
- $log.debug('BulkUserModalCtrl::verifyRoles: skip row ' + uploadRow.line);
- return;
- }
- uploadRow.role = uploadRow.role.trim();
- var foundRole=false;
- for (var i=0; i < appRolesResult.length; i++) {
- if (uploadRow.role.toUpperCase() === appRolesResult[i].rolename.trim().toUpperCase()) {
- if (debug)
- $log.debug('BulkUserModalCtrl::verifyRoles: match on role ' + uploadRow.role);
- foundRole=true;
- break;
- }
- };
- if (!foundRole) {
- if (debug)
- $log.debug('BulkUserModalCtrl::verifyRoles: NO match on role ' + uploadRow.role);
- uploadRow.status = 'Invalid role';
- };
- }); // foreach
- }; // verifyRoles
-
- /**
- * Builds and returns an array of promises to invoke the
- * searchUsers service for each unique Org User UID in the input.
- * Reads and writes scope variable uploadFile, which must be sorted by Org User UID.
- * The promise function writes to closure variable userCheckResult
- */
- $scope.buildUserChecks = () => {
- if (debug)
- $log.debug('BulkUserModalCtrl::buildUserChecks: uploadFile length is ' + $scope.uploadFile.length);
- userCheckResult = [];
- let promises = [];
- let prevRow = null;
- $scope.uploadFile.forEach(function (uploadRow) {
- if (uploadRow.status) {
- if (debug)
- $log.debug('BulkUserModalCtrl::buildUserChecks: skip row ' + uploadRow.line);
- return;
- };
- // detect repeated UIDs
- if (prevRow == null || prevRow.orgUserId.toLowerCase() !== uploadRow.orgUserId.toLowerCase()) {
- if (debug)
- $log.debug('BulkUserModalCtrl::buildUserChecks: create request for orgUserId ' + uploadRow.orgUserId);
- let userPromise = usersService.searchUsers(uploadRow.orgUserId).promise().then( (usersList) => {
- if (typeof usersList[0] !== "undefined") {
- userCheckResult.push({
- orgUserId: usersList[0].orgUserId,
- firstName: usersList[0].firstName,
- lastName: usersList[0].lastName,
- jobTitle: usersList[0].jobTitle
- });
- }
- else {
- // User not found.
- if (debug)
- $log.debug('BulkUserModalCtrl::buildUserChecks: searchUsers returned null');
- }
- }, function(error){
- $log.error('BulkUserModalCtrl::buildUserChecks: searchUsers failed ' + JSON.stringify(error));
- });
- promises.push(userPromise);
- }
- else {
- if (debug)
- $log.debug('BulkUserModalCtrl::buildUserChecks: skip repeated orgUserId ' + uploadRow.orgUserId);
- }
- prevRow = uploadRow;
- }); // foreach
- return promises;
- }; // buildUserChecks
-
- /**
- * Evaluates the result set returned by the user service to set
- * the uploadFile array element status if the user was not found.
- * Reads and writes scope variable uploadFile.
- * Reads closure variable userCheckResult.
- */
- $scope.evalUserCheckResults = () => {
- if (debug)
- $log.debug('BulkUserModalCtrl::evalUserCheckResult: uploadFile length is ' + $scope.uploadFile.length);
- $scope.uploadFile.forEach(function (uploadRow) {
- if (uploadRow.status) {
- if (debug)
- $log.debug('BulkUserModalCtrl::evalUserCheckResults: skip row ' + uploadRow.line);
- return;
- };
- let foundorgUserId = false;
- userCheckResult.forEach(function(userItem) {
- if (uploadRow.orgUserId.toLowerCase() === userItem.orgUserId.toLowerCase()) {
- if (debug)
- $log.debug('BulkUserModalCtrl::evalUserCheckResults: found orgUserId ' + uploadRow.orgUserId);
- foundorgUserId=true;
- };
- });
- if (!foundorgUserId) {
- if (debug)
- $log.debug('BulkUserModalCtrl::evalUserCheckResults: NO match on orgUserId ' + uploadRow.orgUserId);
- uploadRow.status = 'Invalid orgUserId';
- }
- }); // foreach
- }; // evalUserCheckResults
-
- /**
- * Builds and returns an array of promises to invoke the getUserAppRoles
- * service for each unique Org User in the input file.
- * Each promise creates an update to be sent to the remote application
- * with all role names.
- * Reads scope variable uploadFile, which must be sorted by Org User.
- * The promise function writes to closure variable appUserRolesRequest
- */
- $scope.buildAppRoleChecks = () => {
- if (debug)
- $log.debug('BulkUserModalCtrl::buildAppRoleChecks: uploadFile length is ' + $scope.uploadFile.length);
- appUserRolesRequest = [];
- let appId = $scope.selectedApplication.id;
- let promises = [];
- let prevRow = null;
- $scope.uploadFile.forEach( function (uploadRow) {
- if (uploadRow.status) {
- if (debug)
- $log.debug('BulkUserModalCtrl::buildAppRoleChecks: skip row ' + uploadRow.line);
- return;
- }
- // Because the input is sorted, generate only one request for each Org User
- if (prevRow == null || prevRow.orgUserId.toLowerCase() !== uploadRow.orgUserId.toLowerCase()) {
- if (debug)
- $log.debug('BulkUserModalCtrl::buildAppRoleChecks: create request for orgUserId ' + uploadRow.orgUserId);
- let appPromise = usersService.getUserAppRoles(appId, uploadRow.orgUserId).promise().then( (userAppRolesResult) => {
- // Reply for unknown user has all defined roles with isApplied=false on each.
- if (typeof userAppRolesResult[0] !== "undefined") {
- if (debug)
- $log.debug('BulkUserModalCtrl::buildAppRoleChecks: adding result '
- + JSON.stringify(userAppRolesResult));
- appUserRolesRequest.push({
- orgUserId: uploadRow.orgUserId,
- userAppRoles: userAppRolesResult
- });
- } else {
- $log.error('BulkUserModalCtrl::buildAppRoleChecks: getUserAppRoles returned ' + JSON.stringify(userAppRolesResult));
- };
- }, function(error){
- $log.error('BulkUserModalCtrl::buildAppRoleChecks: getUserAppRoles failed ', error);
- });
- promises.push(appPromise);
- } else {
- if (debug)
- $log.debug('BulkUserModalCtrl::buildAppRoleChecks: duplicate orgUserId, skip: '+ uploadRow.orgUserId);
- }
- prevRow = uploadRow;
- }); // foreach
- return promises;
- }; // buildAppRoleChecks
-
- /**
- * Evaluates the result set returned by the app service and adjusts
- * the list of updates to be sent to the remote application by setting
- * isApplied=true for each role name found in the upload file.
- * Reads and writes scope variable uploadFile.
- * Reads closure variable appUserRolesRequest.
- */
- $scope.evalAppRoleCheckResults = () => {
- if (debug)
- $log.debug('BulkUserModalCtrl::evalAppRoleCheckResults: uploadFile length is ' + $scope.uploadFile.length);
- $scope.uploadFile.forEach(function (uploadRow) {
- if (uploadRow.status) {
- if (debug)
- $log.debug('BulkUserModalCtrl::evalAppRoleCheckResults: skip row ' + uploadRow.line);
- return;
- }
- // Search for the match in the app-user-roles array
- appUserRolesRequest.forEach( function (appUserRoleObj) {
- if (uploadRow.orgUserId.toLowerCase() === appUserRoleObj.orgUserId.toLowerCase()) {
- if (debug)
- $log.debug('BulkUserModalCtrl::evalAppRoleCheckResults: match on orgUserId ' + uploadRow.orgUserId);
- let roles = appUserRoleObj.userAppRoles;
- roles.forEach(function (appRoleItem) {
- //if (debug)
- // $log.debug('BulkUserModalCtrl::evalAppRoleCheckResults: checking uploadRow.role='
- // + uploadRow.role + ', appRoleItem.roleName= ' + appRoleItem.roleName);
- if (uploadRow.role === appRoleItem.roleName) {
- if (appRoleItem.isApplied) {
- if (debug)
- $log.debug('BulkUserModalCtrl::evalAppRoleCheckResults: existing role '
- + appRoleItem.roleName);
- uploadRow.status = 'Role exists';
- }
- else {
- if (debug)
- $log.debug('BulkUserModalCtrl::evalAppRoleCheckResults: new role '
- + appRoleItem.roleName);
- // After much back-and-forth I decided a clear indicator
- // is better than blank in the table status column.
- uploadRow.status = 'OK';
- appRoleItem.isApplied = true;
- }
- // This count is not especially interesting.
- // numberUserRolesSucceeded++;
- }
- }); // for each role
- }
- }); // for each result
- }); // for each row
- }; // evalAppRoleCheckResults
-
- /**
- * Sends requests to Portal requesting user role assignment.
- * That endpoint handles creation of the user at the remote app if necessary.
- * Reads closure variable appUserRolesRequest.
- * Invoked by the Next button on the confirmation dialog.
- */
- $scope.updateDB = () => {
- $scope.isProcessing = true;
- $scope.progressMsg = 'Sending requests to application..';
- if (debug)
- $log.debug('BulkUserModalCtrl::updateDB: request length is ' + appUserRolesRequest.length);
- var numberUsersSucceeded = 0;
- let promises = [];
- appUserRolesRequest.forEach(function(appUserRoleObj) {
- if (debug)
- $log.debug('BulkUserModalCtrl::updateDB: appUserRoleObj is ' + JSON.stringify(appUserRoleObj));
- let updateRequest = {
- orgUserId: appUserRoleObj.orgUserId,
- appId: $scope.selectedApplication.id,
- appRoles: appUserRoleObj.userAppRoles
- };
- if (debug)
- $log.debug('BulkUserModalCtrl::updateDB: updateRequest is ' + JSON.stringify(updateRequest));
- let updatePromise = usersService.updateUserAppRoles(updateRequest).promise().then(res => {
- if (debug)
- $log.debug('BulkUserModalCtrl::updateDB: updated successfully: ' + JSON.stringify(res));
- numberUsersSucceeded++;
- }).catch(err => {
- // What to do if one of many fails??
- $log.error('BulkUserModalCtrl::updateDB failed: ', err);
- confirmBoxService.showInformation(
- 'Failed to update the user application roles. ' +
- 'Error: ' + err.status).then(isConfirmed => { });
- }).finally( () => {
- // $log.debug('BulkUserModalCtrl::updateDB: finally()');
- });
- promises.push(updatePromise);
- }); // for each
-
- // Run all the promises
- $q.all(promises).then(function(){
- $scope.isProcessing = false;
- confirmBoxService.showInformation('Processed ' + numberUsersSucceeded + ' users.').then(isConfirmed => {
- // Close the upload-confirm dialog
- ngDialog.close();
- });
- });
- }; // updateDb
-
- // Sets the variable that hides/reveals the user controls
- $scope.step2 = () => {
- this.fileSelected = false;
- $scope.selectedFile = null;
- $scope.fileModel = null;
- this.step1 = false;
- }
-
- // Navigate between dialog screens using step number: 1,2,...
- $scope.navigateBack = () => {
- this.step1 = true;
- this.fileSelected = false;
- };
-
- // Opens a dialog to show the data to be uploaded.
- // Invoked by the upload button on the bulk user dialog.
- $scope.confirmUpload = () => {
- // Start the process
- $scope.readValidateFile();
- // Dialog shows progress
- ngDialog.open({
- templateUrl: 'app/views/users/new-user-dialogs/bulk-user.confirm.html',
- scope: $scope
- });
- };
-
- // Invoked by the Cancel button on the confirmation dialog.
- $scope.cancelUpload = () => {
- ngDialog.close();
- };
-
- init();
- } // constructor
- } // class
- BulkUserModalCtrl.$inject = ['$scope', '$log', '$filter', '$q', 'usersService', 'applicationsService', 'confirmBoxService', 'functionalMenuService', 'ngDialog'];
- angular.module('ecompApp').controller('BulkUserModalCtrl', BulkUserModalCtrl);
-
- angular.module('ecompApp').directive('fileChange', ['$parse', function($parse){
- return {
- require: 'ngModel',
- restrict: 'A',
- link : function($scope, element, attrs, ngModel) {
- var attrHandler = $parse(attrs['fileChange']);
- var handler=function(e) {
- $scope.$apply(function() {
- attrHandler($scope, { $event:e, files:e.target.files } );
- $scope.selectedFile = e.target.files[0].name;
- });
- };
- element[0].addEventListener('change',handler,false);
- }
- }
- }]);
-
- angular.module('ecompApp').filter('csvToObj',function() {
- return function(input) {
- var result = [];
- var len, i, line, o;
- var lines = input.split('\n');
- // Need 1-based index below
- for (len = lines.length, i = 1; i <= len; ++i) {
- // Use 0-based index for array
- line = lines[i - 1].trim();
- if (line.length == 0) {
- // console.log("Skipping blank line");
- result.push({
- line: i,
- orgUserId: '',
- role: '',
- status: 'Blank line'
- });
- continue;
- }
- o = line.split(',');
- if (o.length !== 2) {
- // other lengths not valid for upload
- result.push({
- line: i,
- orgUserId: line,
- role: '',
- status: 'Failed to find 2 comma-separated values'
- });
- }
- else {
- // console.log("Valid line: ", val);
- let entry = {
- line: i,
- orgUserId: o[0],
- role: o[1]
- // leave status undefined, this could be valid.
- };
- if (o[0].toLowerCase() === 'orgUserId') {
- // not valid for upload, so set status
- entry.status = 'Header';
- }
- else if (o[0].trim() == '' || o[1].trim() == '') {
- // defend against line with only a single comma etc.
- entry.status = 'Failed to find 2 non-empty values';
- }
- result.push(entry);
- } // len 2
- } // for
- return result;
- };
- });
-
-
-
-})();
+/*- + * ================================================================================ + * ECOMP Portal + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property + * ================================================================================ + * Licensed 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. + * ================================================================================ + */ +/** + * bulk user upload controller + */ +'use strict'; +(function () { + class BulkUserModalCtrl { + constructor($scope, $log, $filter, $q, usersService, applicationsService, confirmBoxService, functionalMenuService, ngDialog) { + + // Set to true for copious console output + var debug = false; + // Roles fetched from app service + var appRolesResult = []; + // Users fetched from user service + var userCheckResult = []; + // Requests for user-role assignment built by validator + var appUserRolesRequest = []; + + let init = () => { + if (debug) + $log.debug('BulkUserModalCtrl::init'); + // Angular insists on this. + $scope.fileModel = {}; + // Model for drop-down + $scope.adminApps = []; + // Enable modal controls + this.step1 = true; + this.fileSelected = false; + + // Flag that indicates background work is proceeding + $scope.isProcessing = true; + + // Load user's admin applications + applicationsService.getAdminApps().promise().then(apps => { + if (debug) + $log.debug('BulkUserModalCtrl::init: getAdminApps returned' + JSON.stringify(apps)); + if (!apps || typeof(apps) != 'object') { + $log.error('BulkUserModalCtrl::init: getAdminApps returned unexpected data'); + } + else { + if (debug) + $log.debug('BulkUserModalCtrl::init: admin apps length is ', apps.length); + + // Sort app names and populate the drop-down model + let sortedApps = apps.sort(getSortOrder('name', true)); + for (let i = 0; i < sortedApps.length; ++i) { + $scope.adminApps.push({ + index: i, + id: sortedApps[i].id, + value: sortedApps[i].name, + title: sortedApps[i].name + }); + } + // Pick the first one in the list + $scope.selectedApplication = $scope.adminApps[0]; + } + $scope.isProcessing = false; + }).catch(err => { + $log.error('BulkUserModalCtrl::init: getAdminApps threw', err); + $scope.isProcessing = false; + }); + + }; // init + + // Answers a function that compares properties with the specified name. + let getSortOrder = (prop, foldCase) => { + return function(a, b) { + let aProp = foldCase ? a[prop].toLowerCase() : a[prop]; + let bProp = foldCase ? b[prop].toLowerCase() : b[prop]; + if (aProp > bProp) + return 1; + else if (aProp < bProp) + return -1; + else + return 0; + } + } + + //This is a fix for dropdown selection, due to b2b dropdown only update value field + $scope.$watch('selectedApplication.value', (newVal, oldVal) => { + for(var i=0;i<$scope.adminApps.length;i++){ + if($scope.adminApps[i].value==newVal){ + $scope.selectedApplication=angular.copy($scope.adminApps[i]);; + } + } + }); + + // Invoked when user picks an app on the drop-down. + $scope.appSelected = () => { + if (debug) + $log.debug('BulkUserModalCtrl::appSelected: selectedApplication.id is ' + $scope.selectedApplication.id); + this.appSelected = true; + } + + // Caches the file name supplied by the event handler. + $scope.fileChangeHandler = (event, files) => { + this.fileSelected = true; + this.fileToRead = files[0]; + if (debug) + $log.debug("BulkUserModalCtrl::fileChangeHandler: file is ", this.fileToRead); + }; // file change handler + + /** + * Reads the contents of the file, calls portal endpoints + * to validate roles, userIds and existing role assignments; + * ultimately builds array of requests to be sent. + * Creates scope variable with input file contents for + * communication with functions. + * + * This function performs a synchronous step-by-step process + * using asynchronous promises. The code could all be inline + * here but the nesting becomes unwieldy. + */ + $scope.readValidateFile = () => { + $scope.isProcessing = true; + $scope.progressMsg = 'Reading upload file..'; + var reader = new FileReader(); + reader.onload = function(event) { + $scope.uploadFile = $filter('csvToObj')(reader.result); + if (debug) + $log.debug('BulkUserModalCtrl::readValidateFile onload: data length is ' + $scope.uploadFile.length); + // sort input by orgUserId + $scope.uploadFile.sort(getSortOrder('orgUserId', true)); + + let appid = $scope.selectedApplication.id; + $scope.progressMsg = 'Fetching application roles..'; + functionalMenuService.getManagedRolesMenu(appid).then(function (rolesObj) { + if (debug) + $log.debug("BulkUserModalCtrl::readValidateFile: managedRolesMenu returned " + JSON.stringify(rolesObj)); + appRolesResult = rolesObj; + $scope.progressMsg = 'Validating application roles..'; + $scope.verifyRoles(); + + let userPromises = $scope.buildUserChecks(); + if (debug) + $log.debug('BulkUserModalCtrl::readValidateFile: userPromises length is ' + userPromises.length); + $scope.progressMsg = 'Validating Org Users..'; + $q.all(userPromises).then(function() { + if (debug) + $log.debug('BulkUserModalCtrl::readValidateFile: userCheckResult length is ' + userCheckResult.length); + $scope.evalUserCheckResults(); + + let appPromises = $scope.buildAppRoleChecks(); + if (debug) + $log.debug('BulkUserModalCtrl::readValidateFile: appPromises length is ' + appPromises.length); + $scope.progressMsg = 'Querying application for user roles..'; + $q.all(appPromises).then( function() { + if (debug) + $log.debug('BulkUserModalCtrl::readValidateFile: appUserRolesRequest length is ' + appUserRolesRequest.length); + $scope.evalAppRoleCheckResults(); + + // Re sort by line for the confirmation dialog + $scope.uploadFile.sort(getSortOrder('line', false)); + // We're done, confirm box may show the table + if (debug) + $log.debug('BulkUserModalCtrl::readValidateFile inner-then ends'); + $scope.progressMsg = 'Done.'; + $scope.isProcessing = false; + }, + function(error) { + $log.error('BulkUserModalCtrl::readValidateFile: failed retrieving user-app roles'); + $scope.isProcessing = false; + } + ); // then of app promises + }, + function(error) { + $log.error('BulkUserModalCtrl::readValidateFile: failed retrieving user info'); + $scope.isProcessing = false; + } + ); // then of user promises + }, + function(error) { + $log.error('BulkUserModalCtrl::readValidateFile: failed retrieving app role info'); + $scope.isProcessing = false; + } + ); // then of role promise + + } // onload + + // Invoke the reader on the selected file + reader.readAsText(this.fileToRead); + }; + + /** + * Evaluates the result set returned by the app role service. + * Sets an uploadFile array element status if a role is not defined. + * Reads and writes scope variable uploadFile. + * Reads closure variable appRolesResult. + */ + $scope.verifyRoles = () => { + if (debug) + $log.debug('BulkUserModalCtrl::verifyRoles: appRoles is ' + JSON.stringify(appRolesResult)); + // check roles in upload file against defined app roles + $scope.uploadFile.forEach( function (uploadRow) { + // skip rows that already have a defined status: headers etc. + if (uploadRow.status) { + if (debug) + $log.debug('BulkUserModalCtrl::verifyRoles: skip row ' + uploadRow.line); + return; + } + uploadRow.role = uploadRow.role.trim(); + var foundRole=false; + for (var i=0; i < appRolesResult.length; i++) { + if (uploadRow.role.toUpperCase() === appRolesResult[i].rolename.trim().toUpperCase()) { + if (debug) + $log.debug('BulkUserModalCtrl::verifyRoles: match on role ' + uploadRow.role); + foundRole=true; + break; + } + }; + if (!foundRole) { + if (debug) + $log.debug('BulkUserModalCtrl::verifyRoles: NO match on role ' + uploadRow.role); + uploadRow.status = 'Invalid role'; + }; + }); // foreach + }; // verifyRoles + + /** + * Builds and returns an array of promises to invoke the + * searchUsers service for each unique Org User UID in the input. + * Reads and writes scope variable uploadFile, which must be sorted by Org User UID. + * The promise function writes to closure variable userCheckResult + */ + $scope.buildUserChecks = () => { + if (debug) + $log.debug('BulkUserModalCtrl::buildUserChecks: uploadFile length is ' + $scope.uploadFile.length); + userCheckResult = []; + let promises = []; + let prevRow = null; + $scope.uploadFile.forEach(function (uploadRow) { + if (uploadRow.status) { + if (debug) + $log.debug('BulkUserModalCtrl::buildUserChecks: skip row ' + uploadRow.line); + return; + }; + // detect repeated UIDs + if (prevRow == null || prevRow.orgUserId.toLowerCase() !== uploadRow.orgUserId.toLowerCase()) { + if (debug) + $log.debug('BulkUserModalCtrl::buildUserChecks: create request for orgUserId ' + uploadRow.orgUserId); + let userPromise = usersService.searchUsers(uploadRow.orgUserId).promise().then( (usersList) => { + if (typeof usersList[0] !== "undefined") { + userCheckResult.push({ + orgUserId: usersList[0].orgUserId, + firstName: usersList[0].firstName, + lastName: usersList[0].lastName, + jobTitle: usersList[0].jobTitle + }); + } + else { + // User not found. + if (debug) + $log.debug('BulkUserModalCtrl::buildUserChecks: searchUsers returned null'); + } + }, function(error){ + $log.error('BulkUserModalCtrl::buildUserChecks: searchUsers failed ' + JSON.stringify(error)); + }); + promises.push(userPromise); + } + else { + if (debug) + $log.debug('BulkUserModalCtrl::buildUserChecks: skip repeated orgUserId ' + uploadRow.orgUserId); + } + prevRow = uploadRow; + }); // foreach + return promises; + }; // buildUserChecks + + /** + * Evaluates the result set returned by the user service to set + * the uploadFile array element status if the user was not found. + * Reads and writes scope variable uploadFile. + * Reads closure variable userCheckResult. + */ + $scope.evalUserCheckResults = () => { + if (debug) + $log.debug('BulkUserModalCtrl::evalUserCheckResult: uploadFile length is ' + $scope.uploadFile.length); + $scope.uploadFile.forEach(function (uploadRow) { + if (uploadRow.status) { + if (debug) + $log.debug('BulkUserModalCtrl::evalUserCheckResults: skip row ' + uploadRow.line); + return; + }; + let foundorgUserId = false; + userCheckResult.forEach(function(userItem) { + if (uploadRow.orgUserId.toLowerCase() === userItem.orgUserId.toLowerCase()) { + if (debug) + $log.debug('BulkUserModalCtrl::evalUserCheckResults: found orgUserId ' + uploadRow.orgUserId); + foundorgUserId=true; + }; + }); + if (!foundorgUserId) { + if (debug) + $log.debug('BulkUserModalCtrl::evalUserCheckResults: NO match on orgUserId ' + uploadRow.orgUserId); + uploadRow.status = 'Invalid orgUserId'; + } + }); // foreach + }; // evalUserCheckResults + + /** + * Builds and returns an array of promises to invoke the getUserAppRoles + * service for each unique Org User in the input file. + * Each promise creates an update to be sent to the remote application + * with all role names. + * Reads scope variable uploadFile, which must be sorted by Org User. + * The promise function writes to closure variable appUserRolesRequest + */ + $scope.buildAppRoleChecks = () => { + if (debug) + $log.debug('BulkUserModalCtrl::buildAppRoleChecks: uploadFile length is ' + $scope.uploadFile.length); + appUserRolesRequest = []; + let appId = $scope.selectedApplication.id; + let promises = []; + let prevRow = null; + $scope.uploadFile.forEach( function (uploadRow) { + if (uploadRow.status) { + if (debug) + $log.debug('BulkUserModalCtrl::buildAppRoleChecks: skip row ' + uploadRow.line); + return; + } + // Because the input is sorted, generate only one request for each Org User + if (prevRow == null || prevRow.orgUserId.toLowerCase() !== uploadRow.orgUserId.toLowerCase()) { + if (debug) + $log.debug('BulkUserModalCtrl::buildAppRoleChecks: create request for orgUserId ' + uploadRow.orgUserId); + let appPromise = usersService.getUserAppRoles(appId, uploadRow.orgUserId).promise().then( (userAppRolesResult) => { + // Reply for unknown user has all defined roles with isApplied=false on each. + if (typeof userAppRolesResult[0] !== "undefined") { + if (debug) + $log.debug('BulkUserModalCtrl::buildAppRoleChecks: adding result ' + + JSON.stringify(userAppRolesResult)); + appUserRolesRequest.push({ + orgUserId: uploadRow.orgUserId, + userAppRoles: userAppRolesResult + }); + } else { + $log.error('BulkUserModalCtrl::buildAppRoleChecks: getUserAppRoles returned ' + JSON.stringify(userAppRolesResult)); + }; + }, function(error){ + $log.error('BulkUserModalCtrl::buildAppRoleChecks: getUserAppRoles failed ', error); + }); + promises.push(appPromise); + } else { + if (debug) + $log.debug('BulkUserModalCtrl::buildAppRoleChecks: duplicate orgUserId, skip: '+ uploadRow.orgUserId); + } + prevRow = uploadRow; + }); // foreach + return promises; + }; // buildAppRoleChecks + + /** + * Evaluates the result set returned by the app service and adjusts + * the list of updates to be sent to the remote application by setting + * isApplied=true for each role name found in the upload file. + * Reads and writes scope variable uploadFile. + * Reads closure variable appUserRolesRequest. + */ + $scope.evalAppRoleCheckResults = () => { + if (debug) + $log.debug('BulkUserModalCtrl::evalAppRoleCheckResults: uploadFile length is ' + $scope.uploadFile.length); + $scope.uploadFile.forEach(function (uploadRow) { + if (uploadRow.status) { + if (debug) + $log.debug('BulkUserModalCtrl::evalAppRoleCheckResults: skip row ' + uploadRow.line); + return; + } + // Search for the match in the app-user-roles array + appUserRolesRequest.forEach( function (appUserRoleObj) { + if (uploadRow.orgUserId.toLowerCase() === appUserRoleObj.orgUserId.toLowerCase()) { + if (debug) + $log.debug('BulkUserModalCtrl::evalAppRoleCheckResults: match on orgUserId ' + uploadRow.orgUserId); + let roles = appUserRoleObj.userAppRoles; + roles.forEach(function (appRoleItem) { + //if (debug) + // $log.debug('BulkUserModalCtrl::evalAppRoleCheckResults: checking uploadRow.role=' + // + uploadRow.role + ', appRoleItem.roleName= ' + appRoleItem.roleName); + if (uploadRow.role === appRoleItem.roleName) { + if (appRoleItem.isApplied) { + if (debug) + $log.debug('BulkUserModalCtrl::evalAppRoleCheckResults: existing role ' + + appRoleItem.roleName); + uploadRow.status = 'Role exists'; + } + else { + if (debug) + $log.debug('BulkUserModalCtrl::evalAppRoleCheckResults: new role ' + + appRoleItem.roleName); + // After much back-and-forth I decided a clear indicator + // is better than blank in the table status column. + uploadRow.status = 'OK'; + appRoleItem.isApplied = true; + } + // This count is not especially interesting. + // numberUserRolesSucceeded++; + } + }); // for each role + } + }); // for each result + }); // for each row + }; // evalAppRoleCheckResults + + /** + * Sends requests to Portal requesting user role assignment. + * That endpoint handles creation of the user at the remote app if necessary. + * Reads closure variable appUserRolesRequest. + * Invoked by the Next button on the confirmation dialog. + */ + $scope.updateDB = () => { + $scope.isProcessing = true; + $scope.progressMsg = 'Sending requests to application..'; + if (debug) + $log.debug('BulkUserModalCtrl::updateDB: request length is ' + appUserRolesRequest.length); + var numberUsersSucceeded = 0; + let promises = []; + appUserRolesRequest.forEach(function(appUserRoleObj) { + if (debug) + $log.debug('BulkUserModalCtrl::updateDB: appUserRoleObj is ' + JSON.stringify(appUserRoleObj)); + let updateRequest = { + orgUserId: appUserRoleObj.orgUserId, + appId: $scope.selectedApplication.id, + appRoles: appUserRoleObj.userAppRoles + }; + if (debug) + $log.debug('BulkUserModalCtrl::updateDB: updateRequest is ' + JSON.stringify(updateRequest)); + let updatePromise = usersService.updateUserAppRoles(updateRequest).promise().then(res => { + if (debug) + $log.debug('BulkUserModalCtrl::updateDB: updated successfully: ' + JSON.stringify(res)); + numberUsersSucceeded++; + }).catch(err => { + // What to do if one of many fails?? + $log.error('BulkUserModalCtrl::updateDB failed: ', err); + confirmBoxService.showInformation( + 'Failed to update the user application roles. ' + + 'Error: ' + err.status).then(isConfirmed => { }); + }).finally( () => { + // $log.debug('BulkUserModalCtrl::updateDB: finally()'); + }); + promises.push(updatePromise); + }); // for each + + // Run all the promises + $q.all(promises).then(function(){ + $scope.isProcessing = false; + confirmBoxService.showInformation('Processed ' + numberUsersSucceeded + ' users.').then(isConfirmed => { + // Close the upload-confirm dialog + ngDialog.close(); + }); + }); + }; // updateDb + + // Sets the variable that hides/reveals the user controls + $scope.step2 = () => { + this.fileSelected = false; + $scope.selectedFile = null; + $scope.fileModel = null; + this.step1 = false; + } + + // Navigate between dialog screens using step number: 1,2,... + $scope.navigateBack = () => { + this.step1 = true; + this.fileSelected = false; + }; + + // Opens a dialog to show the data to be uploaded. + // Invoked by the upload button on the bulk user dialog. + $scope.confirmUpload = () => { + // Start the process + $scope.readValidateFile(); + // Dialog shows progress + ngDialog.open({ + templateUrl: 'app/views/users/new-user-dialogs/bulk-user.confirm.html', + scope: $scope + }); + }; + + // Invoked by the Cancel button on the confirmation dialog. + $scope.cancelUpload = () => { + ngDialog.close(); + }; + + init(); + } // constructor + } // class + BulkUserModalCtrl.$inject = ['$scope', '$log', '$filter', '$q', 'usersService', 'applicationsService', 'confirmBoxService', 'functionalMenuService', 'ngDialog']; + angular.module('ecompApp').controller('BulkUserModalCtrl', BulkUserModalCtrl); + + angular.module('ecompApp').directive('fileChange', ['$parse', function($parse){ + return { + require: 'ngModel', + restrict: 'A', + link : function($scope, element, attrs, ngModel) { + var attrHandler = $parse(attrs['fileChange']); + var handler=function(e) { + $scope.$apply(function() { + attrHandler($scope, { $event:e, files:e.target.files } ); + $scope.selectedFile = e.target.files[0].name; + }); + }; + element[0].addEventListener('change',handler,false); + } + } + }]); + + angular.module('ecompApp').filter('csvToObj',function() { + return function(input) { + var result = []; + var len, i, line, o; + var lines = input.split('\n'); + // Need 1-based index below + for (len = lines.length, i = 1; i <= len; ++i) { + // Use 0-based index for array + line = lines[i - 1].trim(); + if (line.length == 0) { + // console.log("Skipping blank line"); + result.push({ + line: i, + orgUserId: '', + role: '', + status: 'Blank line' + }); + continue; + } + o = line.split(','); + if (o.length !== 2) { + // other lengths not valid for upload + result.push({ + line: i, + orgUserId: line, + role: '', + status: 'Failed to find 2 comma-separated values' + }); + } + else { + // console.log("Valid line: ", val); + let entry = { + line: i, + orgUserId: o[0], + role: o[1] + // leave status undefined, this could be valid. + }; + if (o[0].toLowerCase() === 'orgUserId') { + // not valid for upload, so set status + entry.status = 'Header'; + } + else if (o[0].trim() == '' || o[1].trim() == '') { + // defend against line with only a single comma etc. + entry.status = 'Failed to find 2 non-empty values'; + } + result.push(entry); + } // len 2 + } // for + return result; + }; + }); + + + +})(); diff --git a/ecomp-portal-FE-common/client/app/views/users/new-user-dialogs/bulk-user.modal.html b/ecomp-portal-FE-common/client/app/views/users/new-user-dialogs/bulk-user.modal.html index 3d479cb9..7945e54a 100644 --- a/ecomp-portal-FE-common/client/app/views/users/new-user-dialogs/bulk-user.modal.html +++ b/ecomp-portal-FE-common/client/app/views/users/new-user-dialogs/bulk-user.modal.html @@ -1,70 +1,76 @@ -<!--
- ================================================================================
- ECOMP Portal
- ================================================================================
- Copyright (C) 2017 AT&T Intellectual Property
- ================================================================================
- Licensed 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 class="bulk-user-modal">
- <div class="title">Bulk User Upload</div>
- <div class="main">
- <div ng-show="bulkUser.step1">
- <div class="upload-instructions">Select Application:</div>
- <div class="c-ecomp-portal-abs-select default">
-
- <select id="bulk-user-dropdown-apps" name="dropdown1" b2b-dropdown ng-model="selectedApplication.value" ng-disabled="isProcessing" ng-class="{disabled: isProcessing}">
- <option b2b-dropdown-list option-repeat="d in adminApps" value="{{d.value}}">{{d.title}}</option>
- </select>
-
- </div>
- </div>
-
- <div ng-hide="bulkUser.step1">
- <div class="upload-instructions">Select Upload File:</div>
-
- <!-- input type=file is difficult to style.
- Instead use a label styled as a button. -->
- <label class="file-label">
- <input type="file"
- file-change="fileChangeHandler($event,files)"
- ng-model="fileModel" />
- <span>Browse...</span>
- </label>{{selectedFile}}
- <div class="upload-instructions">File must have one entry per line with this format:
- <pre>orgUserId, role name</pre>
- </div>
- </div>
-
- <!-- progress indicator in middle -->
- <div ng-show="isProcessing">
- <span class="ecomp-spinner"></span>
- </div>
-
- <div class="dialog-control">
-
- <button id="bulk-user-back-button" class="btn btn-alt btn-small"
- ng-hide="bulkUser.step1" ng-click="navigateBack()">Back</button>
- <button id="bulk-user-next-button" class="btn btn-alt btn-small"
- ng-hide="!bulkUser.step1" ng-click="!isProcessing && step2()"
- ng-class="{disabled: isProcessing}">Next</button>
- <button id="bulk-user-upload-button" class="btn btn-alt btn-small"
- ng-hide="bulkUser.step1"
- ng-click="bulkUser.fileSelected && confirmUpload()"
- ng-class="{disabled: !bulkUser.fileSelected}">Upload</button>
- <button id="bulk-user-cancel-button" class="btn btn-alt btn-small"
- ng-click="closeThisDialog()">Cancel</button>
- </div>
- </div>
-</div>
+<!-- + ================================================================================ + ECOMP Portal + ================================================================================ + Copyright (C) 2017 AT&T Intellectual Property + ================================================================================ + Licensed 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 class="bulk-user-modal"> + <div class="title">Bulk User Upload</div> + <div class="main"> + <div ng-show="bulkUser.step1"> + <div class="upload-instructions">Select Application:</div> + <div class="c-ecomp-portal-abs-select default"> + + <select id="bulk-user-dropdown-apps" name="dropdown1" b2b-dropdown ng-model="selectedApplication.value" ng-disabled="isProcessing" ng-class="{disabled: isProcessing}"> + <option b2b-dropdown-list option-repeat="d in adminApps" value="{{d.value}}">{{d.title}}</option> + </select> + + </div> + </div> + + <div ng-hide="bulkUser.step1"> + <div class="upload-instructions">Select Upload File:</div> + + <!-- input type=file is difficult to style. + Instead use a label styled as a button. --> + <label class="file-label"> + <input type="file" + file-change="fileChangeHandler($event,files)" + ng-model="fileModel" /> + <span>Browse...</span> + </label>{{selectedFile}} + <div class="upload-instructions">File must have one entry per line with this format: + <pre>orgUserId, role name</pre> + </div> + </div> + + <!-- progress indicator in middle --> + <div ng-show="isProcessing"> + <span class="ecomp-spinner"></span> + </div> + + <div class="dialog-control"> + + <button id="bulk-user-back-button" class="btn btn-alt btn-small" + ng-hide="bulkUser.step1" ng-click="navigateBack()">Back</button> + <button id="bulk-user-next-button" class="btn btn-alt btn-small" + ng-hide="!bulkUser.step1" ng-click="!isProcessing && step2()" + ng-class="{disabled: isProcessing}">Next</button> + <button id="bulk-user-upload-button" class="btn btn-alt btn-small" + ng-hide="bulkUser.step1" + ng-click="bulkUser.fileSelected && confirmUpload()" + ng-class="{disabled: !bulkUser.fileSelected}">Upload</button> + <button id="bulk-user-cancel-button" class="btn btn-alt btn-small" + ng-click="closeThisDialog()">Cancel</button> + </div> + </div> +</div> + +<script> +$(document).ready(function(){ + $(".ngdialog-close").attr('id','dialog-close'); +}); +</script> diff --git a/ecomp-portal-FE-common/client/app/views/users/new-user-dialogs/new-user.controller.js b/ecomp-portal-FE-common/client/app/views/users/new-user-dialogs/new-user.controller.js index 882f1e8f..6550a1ee 100644 --- a/ecomp-portal-FE-common/client/app/views/users/new-user-dialogs/new-user.controller.js +++ b/ecomp-portal-FE-common/client/app/views/users/new-user-dialogs/new-user.controller.js @@ -1,216 +1,217 @@ -/*-
- * ================================================================================
- * ECOMP Portal
- * ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property
- * ================================================================================
- * Licensed 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.
- * ================================================================================
- */
-/**
- * Created by nnaffar on 12/20/15.
- */
-'use strict';
-(function () {
- class NewUserModalCtrl {
- constructor($scope, $log, usersService, applicationsService, confirmBoxService) {
- let init = () => {
- //$log.info('NewUserModalCtrl::init');
- this.isSaving = false;
- this.anyChanges = false;
- this.adminApps = [];
- this.isGettingAdminApps = false;
- if($scope.ngDialogData && $scope.ngDialogData.selectedUser && $scope.ngDialogData.dialogState){
- this.selectedUser = $scope.ngDialogData.selectedUser;
- this.dialogState = $scope.ngDialogData.dialogState;
- this.isShowBack = false;
- if(this.dialogState === 3){
- this.getUserAppsRoles();
- }
- }else{
- this.isShowBack = true;
- this.selectedUser = null;
- this.dialogState = 1;
- }
- };
-
- this.appChanged = (index) => {
- let myApp = this.adminApps[index];
- //$log.debug('NewUserModalCtrl::appChanged: index: ', index, '; app id: ', myApp.id, 'app name: ',myApp.name);
- myApp.isChanged = true;
- this.anyChanges = true;
- }
-
- this.deleteApp = (app) => {
- let appMessage = this.selectedUser.firstName + ' ' + this.selectedUser.lastName;
- confirmBoxService.deleteItem(appMessage).then(isConfirmed => {
- if(isConfirmed){
- this.anyChanges = true;
- app.isChanged = true;
- app.isDeleted = true; // use this to hide the app in the display
- app.appRoles.forEach(function(role){
- role.isApplied = false;
- });
- }
- }).catch(err => {
- $log.error('NewUserModalCtrl::deleteApp error: ',err);
- confirmBoxService.showInformation('There was a problem deleting the the applications. ' +
- 'Please try again later. Error: ' + err.status).then(isConfirmed => {});
- });
- };
-
- this.getUserAppsRoles = () => {
- if (!this.selectedUser || !this.selectedUser.orgUserId) {
- $log.error('NewUserModalCtrl::getUserAppsRoles error: No user is selected');
- this.dialogState = 1;
- return;
- }
- //$log.debug('NewUserModalCtrl::getUserAppsRoles: about to call getAdminAppsSimpler');
- this.isGettingAdminApps = true;
- applicationsService.getAdminAppsSimpler().then((apps) => {
- //$log.debug('NewUserModalCtrl::getUserAppsRoles: beginning of then for getAdminAppsSimpler');
- this.isGettingAdminApps = false;
- if (!apps || !apps.length) {
- $log.error('NewUserModalCtrl::getUserAppsRoles error: no admin apps found');
- return null;
- }
- //$log.debug('NewUserModalCtrl::getUserAppsRoles: then for getAdminAppsSimpler: step 2');
- //$log.debug('NewUserModalCtrl::getUserAppsRoles: admin apps: ', apps);
- this.adminApps = apps;
- this.dialogState = 3;
- this.userAppRoles = {};
- this.numberAppsProcessed = 0;
- this.isLoading = true;
- apps.forEach(app => {
- //$log.debug('NewUserModalCtrl::getUserAppsRoles: app: id: ', app.id, 'name: ',app.name);
- // Keep track of which app has changed, so we know which apps to update using a BE API
- app.isChanged = false;
- // Each of these specifies a state, which corresponds to a different message and style that gets displayed
- app.isLoading = true;
- app.isError = false;
- app.isDeleted = false;
- app.printNoChanges = false;
- app.isUpdating = false;
- app.isErrorUpdating = false;
- app.isDoneUpdating = false;
- app.errorMessage = "";
- usersService.getUserAppRoles(app.id, this.selectedUser.orgUserId).promise().then((userAppRolesResult) => {
- //$log.debug('NewUserModalCtrl::getUserAppsRoles: got a result for app: ',app.id,': ',app.name,': ',userAppRolesResult);
- app.appRoles = userAppRolesResult;
- app.isLoading = false;
-
- }).catch(err => {
- $log.error(err);
- app.isError = true;
- app.isLoading = false;
- app.errorMessage = err.headers('FEErrorString');
- //$log.debug('NewUserModalCtrl::getUserAppsRoles: in new-user.controller: response header: '+err.headers('FEErrorString'));
- }).finally(()=>{
- this.numberAppsProcessed++;
- if (this.numberAppsProcessed === this.adminApps.length) {
- this.isLoading = false;
- }
- });
- })
- return;
- }).catch(err => {
- $log.error(err);
- })
-
- }
-
- /**
- * Update the selected user apps with the new roles.
- * If no roles remain, set the user to inactive.
- */
- this.updateUserAppsRoles = () => {
- // $log.debug('NewUserModalCtrl::updateUserAppsRoles: entering updateUserAppsRoles');
- if(!this.selectedUser || !this.selectedUser.orgUserId || !this.adminApps){
- $log.error('NewUserModalCtrl::updateUserAppsRoles: mmissing arguments');
- return;
- }
- this.isSaving = true;
- //$log.debug('NewUserModalCtrl::updateUserAppsRoles: going to update user: ' + this.selectedUser.orgUserId);
- this.numberAppsProcessed = 0;
- this.numberAppsSucceeded = 0;
- this.adminApps.forEach(app => {
- if (app.isChanged) {
- //$log.debug('NewUserModalCtrl::updateUserAppsRoles: app roles have changed; going to update: id: ', app.id, '; name: ', app.name);
- app.isUpdating = true;
- var newUserAppRoles = {
- orgUserId: this.selectedUser.orgUserId,
- appId: app.id,
- appRoles: app.appRoles,
- appName: app.name
- };
- usersService.updateUserAppRoles(newUserAppRoles).promise()
- .then(res => {
- //$log.debug('NewUserModalCtrl::updateUserAppsRoles: User app roles updated successfully on app: ',app.id);
- app.isUpdating = false;
- app.isDoneUpdating = true;
- this.numberAppsSucceeded++;
- }).catch(err => {
- $log.error(err);
- app.isErrorUpdating = true;
- confirmBoxService.showInformation(
- 'Failed to update the user application roles: ' + err.status)
- .then(isConfirmed => {});
- }).finally(()=>{
- this.numberAppsProcessed++;
- if (this.numberAppsProcessed === this.adminApps.length) {
- this.isSaving = false; // hide the spinner
- }
- if (this.numberAppsSucceeded === this.adminApps.length) {
- $scope.closeThisDialog(true);//close and resolve dialog promise with true (to update the table)
- }
- })
- } else {
- //$log.debug('NewUserModalCtrl::updateUserAppsRoles: app roles have NOT changed; NOT going to update: id: ', app.id, '; name: ', app.name);
- app.noChanges = true;
- app.isError = false; //remove the error message; just show the No Changes messages
- this.numberAppsProcessed++;
- this.numberAppsSucceeded++;
- if (this.numberAppsProcessed === this.adminApps.length) {
- this.isSaving = false; // hide the spinner
- }
- if (this.numberAppsSucceeded === this.adminApps.length) {
- $scope.closeThisDialog(true);//close and resolve dialog promise with true (to update the table)
- }
- }
- });
- };
-
- /**
- * Navigate between dialog screens using step number: 1,2,...
- */
- this.navigateBack = () => {
- if (this.dialogState === 1) {
- //back from 1st screen?
- }
- if (this.dialogState === 3) {
- this.dialogState = 1;
- }
- };
-
- init();
-
- $scope.$on('$stateChangeStart', e => {
- //Disable navigation when modal is opened
- //**Nabil - note: this will cause the history back state to be replaced with current state
- e.preventDefault();
- });
- }
- }
- NewUserModalCtrl.$inject = ['$scope', '$log', 'usersService', 'applicationsService', 'confirmBoxService'];
- angular.module('ecompApp').controller('NewUserModalCtrl', NewUserModalCtrl);
-})();
+/*- + * ================================================================================ + * ECOMP Portal + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property + * ================================================================================ + * Licensed 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. + * ================================================================================ + */ +/** + * Created by nnaffar on 12/20/15. + */ +'use strict'; +(function () { + class NewUserModalCtrl { + constructor($scope, $log, usersService, applicationsService, confirmBoxService) { + var extRequestValue = false; + let init = () => { + //$log.info('NewUserModalCtrl::init'); + this.isSaving = false; + this.anyChanges = false; + this.adminApps = []; + this.isGettingAdminApps = false; + if($scope.ngDialogData && $scope.ngDialogData.selectedUser && $scope.ngDialogData.dialogState){ + this.selectedUser = $scope.ngDialogData.selectedUser; + this.dialogState = $scope.ngDialogData.dialogState; + this.isShowBack = false; + if(this.dialogState === 3){ + this.getUserAppsRoles(); + } + }else{ + this.isShowBack = true; + this.selectedUser = null; + this.dialogState = 1; + } + }; + + this.appChanged = (index) => { + let myApp = this.adminApps[index]; + //$log.debug('NewUserModalCtrl::appChanged: index: ', index, '; app id: ', myApp.id, 'app name: ',myApp.name); + myApp.isChanged = true; + this.anyChanges = true; + } + + this.deleteApp = (app) => { + let appMessage = this.selectedUser.firstName + ' ' + this.selectedUser.lastName; + confirmBoxService.deleteItem(appMessage).then(isConfirmed => { + if(isConfirmed){ + this.anyChanges = true; + app.isChanged = true; + app.isDeleted = true; // use this to hide the app in the display + app.appRoles.forEach(function(role){ + role.isApplied = false; + }); + } + }).catch(err => { + $log.error('NewUserModalCtrl::deleteApp error: ',err); + confirmBoxService.showInformation('There was a problem deleting the the applications. ' + + 'Please try again later. Error: ' + err.status).then(isConfirmed => {}); + }); + }; + + this.getUserAppsRoles = () => { + if (!this.selectedUser || !this.selectedUser.orgUserId) { + $log.error('NewUserModalCtrl::getUserAppsRoles error: No user is selected'); + this.dialogState = 1; + return; + } + //$log.debug('NewUserModalCtrl::getUserAppsRoles: about to call getAdminAppsSimpler'); + this.isGettingAdminApps = true; + applicationsService.getAdminAppsSimpler().then((apps) => { + //$log.debug('NewUserModalCtrl::getUserAppsRoles: beginning of then for getAdminAppsSimpler'); + this.isGettingAdminApps = false; + if (!apps || !apps.length) { + $log.error('NewUserModalCtrl::getUserAppsRoles error: no admin apps found'); + return null; + } + //$log.debug('NewUserModalCtrl::getUserAppsRoles: then for getAdminAppsSimpler: step 2'); + //$log.debug('NewUserModalCtrl::getUserAppsRoles: admin apps: ', apps); + this.adminApps = apps; + this.dialogState = 3; + this.userAppRoles = {}; + this.numberAppsProcessed = 0; + this.isLoading = true; + apps.forEach(app => { + //$log.debug('NewUserModalCtrl::getUserAppsRoles: app: id: ', app.id, 'name: ',app.name); + // Keep track of which app has changed, so we know which apps to update using a BE API + app.isChanged = false; + // Each of these specifies a state, which corresponds to a different message and style that gets displayed + app.isLoading = true; + app.isError = false; + app.isDeleted = false; + app.printNoChanges = false; + app.isUpdating = false; + app.isErrorUpdating = false; + app.isDoneUpdating = false; + app.errorMessage = ""; + usersService.getUserAppRoles(app.id, this.selectedUser.orgUserId, extRequestValue).promise().then((userAppRolesResult) => { + //$log.debug('NewUserModalCtrl::getUserAppsRoles: got a result for app: ',app.id,': ',app.name,': ',userAppRolesResult); + app.appRoles = userAppRolesResult; + app.isLoading = false; + + }).catch(err => { + $log.error(err); + app.isError = true; + app.isLoading = false; + app.errorMessage = err.headers('FEErrorString'); + //$log.debug('NewUserModalCtrl::getUserAppsRoles: in new-user.controller: response header: '+err.headers('FEErrorString')); + }).finally(()=>{ + this.numberAppsProcessed++; + if (this.numberAppsProcessed === this.adminApps.length) { + this.isLoading = false; + } + }); + }) + return; + }).catch(err => { + $log.error(err); + }) + + } + + /** + * Update the selected user apps with the new roles. + * If no roles remain, set the user to inactive. + */ + this.updateUserAppsRoles = () => { + // $log.debug('NewUserModalCtrl::updateUserAppsRoles: entering updateUserAppsRoles'); + if(!this.selectedUser || !this.selectedUser.orgUserId || !this.adminApps){ + $log.error('NewUserModalCtrl::updateUserAppsRoles: mmissing arguments'); + return; + } + this.isSaving = true; + //$log.debug('NewUserModalCtrl::updateUserAppsRoles: going to update user: ' + this.selectedUser.orgUserId); + this.numberAppsProcessed = 0; + this.numberAppsSucceeded = 0; + this.adminApps.forEach(app => { + if (app.isChanged) { + //$log.debug('NewUserModalCtrl::updateUserAppsRoles: app roles have changed; going to update: id: ', app.id, '; name: ', app.name); + app.isUpdating = true; + var newUserAppRoles = { + orgUserId: this.selectedUser.orgUserId, + appId: app.id, + appRoles: app.appRoles, + appName: app.name + }; + usersService.updateUserAppRoles(newUserAppRoles).promise() + .then(res => { + //$log.debug('NewUserModalCtrl::updateUserAppsRoles: User app roles updated successfully on app: ',app.id); + app.isUpdating = false; + app.isDoneUpdating = true; + this.numberAppsSucceeded++; + }).catch(err => { + $log.error(err); + app.isErrorUpdating = true; + confirmBoxService.showInformation( + 'Failed to update the user application roles: ' + err.status) + .then(isConfirmed => {}); + }).finally(()=>{ + this.numberAppsProcessed++; + if (this.numberAppsProcessed === this.adminApps.length) { + this.isSaving = false; // hide the spinner + } + if (this.numberAppsSucceeded === this.adminApps.length) { + $scope.closeThisDialog(true);//close and resolve dialog promise with true (to update the table) + } + }) + } else { + //$log.debug('NewUserModalCtrl::updateUserAppsRoles: app roles have NOT changed; NOT going to update: id: ', app.id, '; name: ', app.name); + app.noChanges = true; + app.isError = false; //remove the error message; just show the No Changes messages + this.numberAppsProcessed++; + this.numberAppsSucceeded++; + if (this.numberAppsProcessed === this.adminApps.length) { + this.isSaving = false; // hide the spinner + } + if (this.numberAppsSucceeded === this.adminApps.length) { + $scope.closeThisDialog(true);//close and resolve dialog promise with true (to update the table) + } + } + }); + }; + + /** + * Navigate between dialog screens using step number: 1,2,... + */ + this.navigateBack = () => { + if (this.dialogState === 1) { + //back from 1st screen? + } + if (this.dialogState === 3) { + this.dialogState = 1; + } + }; + + init(); + + $scope.$on('$stateChangeStart', e => { + //Disable navigation when modal is opened + //**Nabil - note: this will cause the history back state to be replaced with current state + e.preventDefault(); + }); + } + } + NewUserModalCtrl.$inject = ['$scope', '$log', 'usersService', 'applicationsService', 'confirmBoxService']; + angular.module('ecompApp').controller('NewUserModalCtrl', NewUserModalCtrl); +})(); diff --git a/ecomp-portal-FE-common/client/app/views/users/new-user-dialogs/new-user.controller.spec.js b/ecomp-portal-FE-common/client/app/views/users/new-user-dialogs/new-user.controller.spec.js index 8d5ac749..bdc29583 100644 --- a/ecomp-portal-FE-common/client/app/views/users/new-user-dialogs/new-user.controller.spec.js +++ b/ecomp-portal-FE-common/client/app/views/users/new-user-dialogs/new-user.controller.spec.js @@ -1,255 +1,255 @@ -/*-
- * ================================================================================
- * ECOMP Portal
- * ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property
- * ================================================================================
- * Licensed 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.
- * ================================================================================
- */
-/**
- * Created by nnaffar on 12/20/15.
- */
-'use strict';
-
-describe('Controller: NewUserModalCtrl ', () => {
- beforeEach(module('testUtils'));
- beforeEach(module('ecompApp'));
-
- let promisesTestUtils;
- //destroy $http default cache before starting to prevent the error 'default cache already exists'
- //_promisesTestUtils_ comes from testUtils for promises resolve/reject
- beforeEach(inject((_CacheFactory_, _promisesTestUtils_)=> {
- _CacheFactory_.destroyAll();
- promisesTestUtils = _promisesTestUtils_;
- }));
-
- let newUser, $controller, $q, $rootScope, $log, $scope;
-
- let applicationsServiceMock, usersServiceMock, confirmBoxServiceMock;
- let deferredAdminApps, deferredUsersAccounts, deferredUsersAppRoles, deferredUsersAppRoleUpdate;
-
- beforeEach(inject((_$controller_, _$q_, _$rootScope_, _$log_)=> {
- $rootScope = _$rootScope_;
- $q = _$q_;
- $controller = _$controller_;
- $log = _$log_;
- }));
-
- beforeEach(()=> {
- [deferredAdminApps, deferredUsersAccounts, deferredUsersAppRoles, deferredUsersAppRoleUpdate] = [$q.defer(),$q.defer(), $q.defer(), $q.defer()];
-
- /*applicationsServiceMock = {
- getAdminApps: () => {
- var promise = () => {return deferredAdminApps.promise};
- var cancel = jasmine.createSpy();
- return {
- promise: promise,
- cancel: cancel
- }
- }
- };*/
-
- confirmBoxServiceMock = {
- deleteItem: () => {
- var promise = () => {return deferredAdminApps.promise};
- var cancel = jasmine.createSpy();
- return {
- promise: promise,
- cancel: cancel
- }
- }
- };
-
- applicationsServiceMock = jasmine.createSpyObj('applicationsServiceMock', ['getAdminAppsSimpler']);
- applicationsServiceMock.getAdminAppsSimpler.and.returnValue(deferredAdminApps.promise);
-
- usersServiceMock = jasmine.createSpyObj('usersServiceMock', ['getAccountUsers','getUserAppRoles','updateUserAppsRoles']);
-
- //applicationsServiceMock.getAdminApps().promise().and.returnValue(deferredAdminApps.promise);
- usersServiceMock.getAccountUsers.and.returnValue(deferredUsersAccounts.promise);
- usersServiceMock.getUserAppRoles.and.returnValue(deferredUsersAppRoles.promise);
- usersServiceMock.updateUserAppsRoles.and.returnValue(deferredUsersAppRoleUpdate.promise);
-
- $scope = $rootScope.$new();
- newUser = $controller('NewUserModalCtrl', {
- $scope: $scope,
- $log: $log,
- usersService: usersServiceMock,
- applicationsService: applicationsServiceMock,
- confirmBoxService: confirmBoxServiceMock
- });
- //$scope.users = users;
- });
-
- /*beforeEach(()=> {
- scope = $rootScope.$new();
- newUser = $controller('NewUserModalCtrl', {
- $scope: scope,
- $log: $log,
- usersService: usersService,
- applicationsService: applicationsService,
- confirmBoxService: confirmBoxService
- });
- });*/
-
-
- it('should open modal window without user when no user is selected', ()=> {
- expect(newUser.selectedUser).toBe(null);
- });
-
- it('should open modal window with selectedUser apps roles when user is selected', ()=> {
- let roles = {apps: [{id: 1, appRoles: [{id: 3, isApplied: true}]}]};
- let someUser = {orgUserId: 'asdfjl'};
-
- deferredUsersAppRoles.resolve(roles);
- deferredAdminApps.resolve(roles.apps);
-
- $scope.ngDialogData = {
- selectedUser: someUser,
- dialogState: 2
- };
-
- //inject ngDialogData to the scope controller
- newUser = $controller('NewUserModalCtrl', {
- $scope: $scope,
- $log: $log,
- usersService: usersServiceMock,
- applicationsService: applicationsServiceMock,
- confirmBoxService: confirmBoxServiceMock
- });
-
- newUser.getUserAppsRoles();
- $scope.$apply();
-
- expect(newUser.selectedUser).toBe(someUser);
- expect(newUser.adminApps).toEqual(roles.apps);
- });
-
- it('should push to apps order list only apps that has applied roles when initializing', () => {
- let roles = {apps: [{appId: 13, appRoles: [{id: 3, isApplied: true}]},{appId: 20, appRoles: [{id: 3, isApplied: false}]}]};
- let someUser = {orgUserId: 'asdfjl'};
-
- deferredUsersAppRoles.resolve(roles);
- //deferredAdminApps.resolve(roles.apps);
-
- $scope.ngDialogData = {
- selectedUser: someUser,
- dialogState: 2
- };
-
- //inject ngDialogData to the scope controller
- newUser = $controller('NewUserModalCtrl', {
- $scope: $scope,
- $log: $log,
- usersService: usersServiceMock,
- applicationsService: applicationsServiceMock,
- confirmBoxService: confirmBoxServiceMock
- });
-
- $scope.$apply();
-
- // expect(newUser.appsOrder).toEqual([13]);
- });
-
- it('should push app to apps order list when applying at least one role to user from app', () => {
- let roles = {apps: [{appId: 13, appRoles: [{id: 3, isApplied: true}]},{appId: 20, appRoles: [{id: 3, isApplied: false}]}]};
- let someUser = {orgUserId: 'asdfjl'};
-
- // promisesTestUtils.resolvePromise(usersService, 'getUserAppsRoles', roles);
- deferredUsersAppRoles.resolve(roles);
-
- $scope.ngDialogData = {
- selectedUser: someUser,
- dialogState: 2
- };
-
- //inject ngDialogData to the scope controller
- newUser = $controller('NewUserModalCtrl', {
- $scope: $scope,
- $log: $log,
- usersService: usersServiceMock,
- applicationsService: applicationsServiceMock,
- confirmBoxService: confirmBoxServiceMock
- });
-
- //$scope.$apply();
- //newUser.updateAppsOrder({appId: 39, appRoles: [{id: 13, isApplied: true}]});
- $scope.$apply();
-
- // expect(newUser.appsOrder).toEqual([13, 39]);
- });
-
-
- it('should remove app from list when removing all user roles in it', () => {
- let roles = {apps: [{appName: 'aaa', appId: 13, appRoles: [{id: 3, isApplied: true}]},{appName: 'vvv', appId: 20, appRoles: [{id: 3, isApplied: true}]}]};
- let someUser = {orgUserId: 'asdfjl'};
-
- // promisesTestUtils.resolvePromise(usersService, 'getUserAppsRoles', roles);
- promisesTestUtils.resolvePromise(confirmBoxServiceMock, 'deleteItem', true);
-
- deferredUsersAppRoles.resolve(roles);
-
- $scope.ngDialogData = {
- selectedUser: someUser,
- dialogState: 2
- };
-
- //inject ngDialogData to the scope controller
- newUser = $controller('NewUserModalCtrl', {
- $scope: $scope,
- $log: $log,
- usersService: usersServiceMock,
- applicationsService: applicationsServiceMock,
- confirmBoxService: confirmBoxServiceMock
- });
-
- $scope.$apply();
- newUser.deleteApp(roles.apps[0]);
- $scope.$apply();
-
- // expect(newUser.appsOrder).toEqual([20]);
- });
-
- it('should close the modal when update changes succeeded', () => {
- let roles = {apps: [{appName: 'aaa', appId: 13, appRoles: [{id: 3, isApplied: true}]},{appName: 'vvv', appId: 20, appRoles: [{id: 3, isApplied: true}]}]};
- let someUser = {orgUserId: 'asdfjl'};
- //promisesTestUtils.resolvePromise(usersServiceMock, 'getUserAppsRoles', roles);
- //promisesTestUtils.resolvePromise(usersServiceMock, 'updateUserAppsRoles');
- deferredUsersAppRoles.resolve(roles);
- deferredUsersAppRoleUpdate.resolve();
- deferredAdminApps.resolve(roles.apps);
-
- $scope.ngDialogData = {
- selectedUser: someUser,
- dialogState: 2
- };
-
- //inject ngDialogData to the scope controller
- newUser = $controller('NewUserModalCtrl', {
- $scope: $scope,
- $log: $log,
- usersService: usersServiceMock,
- applicationsService: applicationsServiceMock,
- confirmBoxService: confirmBoxServiceMock
- });
- $scope.closeThisDialog = function(){};
- spyOn($scope, 'closeThisDialog');
-
- newUser.getUserAppsRoles();
- $scope.$apply();
- newUser.updateUserAppsRoles();
- $scope.$apply();
- expect($scope.closeThisDialog).toHaveBeenCalledWith(true);
- });
- });
+/*- + * ================================================================================ + * ECOMP Portal + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property + * ================================================================================ + * Licensed 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. + * ================================================================================ + */ +/** + * Created by nnaffar on 12/20/15. + */ +'use strict'; + +describe('Controller: NewUserModalCtrl ', () => { + beforeEach(module('testUtils')); + beforeEach(module('ecompApp')); + + let promisesTestUtils; + //destroy $http default cache before starting to prevent the error 'default cache already exists' + //_promisesTestUtils_ comes from testUtils for promises resolve/reject + beforeEach(inject((_CacheFactory_, _promisesTestUtils_)=> { + _CacheFactory_.destroyAll(); + promisesTestUtils = _promisesTestUtils_; + })); + + let newUser, $controller, $q, $rootScope, $log, $scope; + + let applicationsServiceMock, usersServiceMock, confirmBoxServiceMock; + let deferredAdminApps, deferredUsersAccounts, deferredUsersAppRoles, deferredUsersAppRoleUpdate; + + beforeEach(inject((_$controller_, _$q_, _$rootScope_, _$log_)=> { + $rootScope = _$rootScope_; + $q = _$q_; + $controller = _$controller_; + $log = _$log_; + })); + + beforeEach(()=> { + [deferredAdminApps, deferredUsersAccounts, deferredUsersAppRoles, deferredUsersAppRoleUpdate] = [$q.defer(),$q.defer(), $q.defer(), $q.defer()]; + + /*applicationsServiceMock = { + getAdminApps: () => { + var promise = () => {return deferredAdminApps.promise}; + var cancel = jasmine.createSpy(); + return { + promise: promise, + cancel: cancel + } + } + };*/ + + confirmBoxServiceMock = { + deleteItem: () => { + var promise = () => {return deferredAdminApps.promise}; + var cancel = jasmine.createSpy(); + return { + promise: promise, + cancel: cancel + } + } + }; + + applicationsServiceMock = jasmine.createSpyObj('applicationsServiceMock', ['getAdminAppsSimpler']); + applicationsServiceMock.getAdminAppsSimpler.and.returnValue(deferredAdminApps.promise); + + usersServiceMock = jasmine.createSpyObj('usersServiceMock', ['getAccountUsers','getUserAppRoles','updateUserAppsRoles']); + + //applicationsServiceMock.getAdminApps().promise().and.returnValue(deferredAdminApps.promise); + usersServiceMock.getAccountUsers.and.returnValue(deferredUsersAccounts.promise); + usersServiceMock.getUserAppRoles.and.returnValue(deferredUsersAppRoles.promise); + usersServiceMock.updateUserAppsRoles.and.returnValue(deferredUsersAppRoleUpdate.promise); + + $scope = $rootScope.$new(); + newUser = $controller('NewUserModalCtrl', { + $scope: $scope, + $log: $log, + usersService: usersServiceMock, + applicationsService: applicationsServiceMock, + confirmBoxService: confirmBoxServiceMock + }); + //$scope.users = users; + }); + + /*beforeEach(()=> { + scope = $rootScope.$new(); + newUser = $controller('NewUserModalCtrl', { + $scope: scope, + $log: $log, + usersService: usersService, + applicationsService: applicationsService, + confirmBoxService: confirmBoxService + }); + });*/ + + + it('should open modal window without user when no user is selected', ()=> { + expect(newUser.selectedUser).toBe(null); + }); + + it('should open modal window with selectedUser apps roles when user is selected', ()=> { + let roles = {apps: [{id: 1, appRoles: [{id: 3, isApplied: true}]}]}; + let someUser = {orgUserId: 'asdfjl'}; + + deferredUsersAppRoles.resolve(roles); + deferredAdminApps.resolve(roles.apps); + + $scope.ngDialogData = { + selectedUser: someUser, + dialogState: 2 + }; + + //inject ngDialogData to the scope controller + newUser = $controller('NewUserModalCtrl', { + $scope: $scope, + $log: $log, + usersService: usersServiceMock, + applicationsService: applicationsServiceMock, + confirmBoxService: confirmBoxServiceMock + }); + + newUser.getUserAppsRoles(); + $scope.$apply(); + + expect(newUser.selectedUser).toBe(someUser); + expect(newUser.adminApps).toEqual(roles.apps); + }); + + it('should push to apps order list only apps that has applied roles when initializing', () => { + let roles = {apps: [{appId: 13, appRoles: [{id: 3, isApplied: true}]},{appId: 20, appRoles: [{id: 3, isApplied: false}]}]}; + let someUser = {orgUserId: 'asdfjl'}; + + deferredUsersAppRoles.resolve(roles); + //deferredAdminApps.resolve(roles.apps); + + $scope.ngDialogData = { + selectedUser: someUser, + dialogState: 2 + }; + + //inject ngDialogData to the scope controller + newUser = $controller('NewUserModalCtrl', { + $scope: $scope, + $log: $log, + usersService: usersServiceMock, + applicationsService: applicationsServiceMock, + confirmBoxService: confirmBoxServiceMock + }); + + $scope.$apply(); + + // expect(newUser.appsOrder).toEqual([13]); + }); + + it('should push app to apps order list when applying at least one role to user from app', () => { + let roles = {apps: [{appId: 13, appRoles: [{id: 3, isApplied: true}]},{appId: 20, appRoles: [{id: 3, isApplied: false}]}]}; + let someUser = {orgUserId: 'asdfjl'}; + + // promisesTestUtils.resolvePromise(usersService, 'getUserAppsRoles', roles); + deferredUsersAppRoles.resolve(roles); + + $scope.ngDialogData = { + selectedUser: someUser, + dialogState: 2 + }; + + //inject ngDialogData to the scope controller + newUser = $controller('NewUserModalCtrl', { + $scope: $scope, + $log: $log, + usersService: usersServiceMock, + applicationsService: applicationsServiceMock, + confirmBoxService: confirmBoxServiceMock + }); + + //$scope.$apply(); + //newUser.updateAppsOrder({appId: 39, appRoles: [{id: 13, isApplied: true}]}); + $scope.$apply(); + + // expect(newUser.appsOrder).toEqual([13, 39]); + }); + + + it('should remove app from list when removing all user roles in it', () => { + let roles = {apps: [{appName: 'aaa', appId: 13, appRoles: [{id: 3, isApplied: true}]},{appName: 'vvv', appId: 20, appRoles: [{id: 3, isApplied: true}]}]}; + let someUser = {orgUserId: 'asdfjl'}; + + // promisesTestUtils.resolvePromise(usersService, 'getUserAppsRoles', roles); + promisesTestUtils.resolvePromise(confirmBoxServiceMock, 'deleteItem', true); + + deferredUsersAppRoles.resolve(roles); + + $scope.ngDialogData = { + selectedUser: someUser, + dialogState: 2 + }; + + //inject ngDialogData to the scope controller + newUser = $controller('NewUserModalCtrl', { + $scope: $scope, + $log: $log, + usersService: usersServiceMock, + applicationsService: applicationsServiceMock, + confirmBoxService: confirmBoxServiceMock + }); + + $scope.$apply(); + newUser.deleteApp(roles.apps[0]); + $scope.$apply(); + + // expect(newUser.appsOrder).toEqual([20]); + }); + + it('should close the modal when update changes succeeded', () => { + let roles = {apps: [{appName: 'aaa', appId: 13, appRoles: [{id: 3, isApplied: true}]},{appName: 'vvv', appId: 20, appRoles: [{id: 3, isApplied: true}]}]}; + let someUser = {orgUserId: 'asdfjl'}; + //promisesTestUtils.resolvePromise(usersServiceMock, 'getUserAppsRoles', roles); + //promisesTestUtils.resolvePromise(usersServiceMock, 'updateUserAppsRoles'); + deferredUsersAppRoles.resolve(roles); + deferredUsersAppRoleUpdate.resolve(); + deferredAdminApps.resolve(roles.apps); + + $scope.ngDialogData = { + selectedUser: someUser, + dialogState: 2 + }; + + //inject ngDialogData to the scope controller + newUser = $controller('NewUserModalCtrl', { + $scope: $scope, + $log: $log, + usersService: usersServiceMock, + applicationsService: applicationsServiceMock, + confirmBoxService: confirmBoxServiceMock + }); + $scope.closeThisDialog = function(){}; + spyOn($scope, 'closeThisDialog'); + + newUser.getUserAppsRoles(); + $scope.$apply(); + newUser.updateUserAppsRoles(); + $scope.$apply(); + expect($scope.closeThisDialog).toHaveBeenCalledWith(true); + }); + }); diff --git a/ecomp-portal-FE-common/client/app/views/users/new-user-dialogs/new-user.modal.html b/ecomp-portal-FE-common/client/app/views/users/new-user-dialogs/new-user.modal.html index 5f26152b..5fec021a 100644 --- a/ecomp-portal-FE-common/client/app/views/users/new-user-dialogs/new-user.modal.html +++ b/ecomp-portal-FE-common/client/app/views/users/new-user-dialogs/new-user.modal.html @@ -1,84 +1,90 @@ -<!--
- ================================================================================
- ECOMP Portal
- ================================================================================
- Copyright (C) 2017 AT&T Intellectual Property
- ================================================================================
- Licensed 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 class="new-user-modal">
-
- <div class="search-users" ng-show="newUser.dialogState===1">
-
- <search-users search-title="New User"
- selected-user="newUser.selectedUser"></search-users>
-
- <div class="dialog-control">
- <button class="btn btn-alt btn-small" id="next-button" ng-click="newUser.selectedUser && newUser.getUserAppsRoles()"
- ng-class="{disabled: !newUser.selectedUser}">Next
- </button>
- <button class="btn btn-alt btn-small" id="cancel-button" ng-click="closeThisDialog()">Cancel</button>
-
- </div>
- </div>
-
- <div class="user-apps-roles" ng-show="newUser.dialogState===3">
- <div class="title"
- ng-bind="newUser.selectedUser.firstName + ' ' + newUser.selectedUser.lastName + ' (' + newUser.selectedUser.orgUserId + ')'"></div>
-
-
- <div class="app-roles-main">
- <div class="app-roles-main-title">
- <span class="left">Access and roles:</span>
- </div>
-
- <div class="app-roles-list">
- <div class="app-item" ng-repeat="app in (newUser.adminApps) track by app.id" id="app-name-{{app.name.split(' ').join('-')}}" ng-show="!app.isDeleted">
- <div class="app-item-left" id="div-app-name-{{app.name.split(' ').join('-')}}">{{app.name | elipsis: 27}}</div>
- <div class="app-item-right" id="div-app-name-dropdown-{{app.name.split(' ').join('-')}}" ng-show="!app.isError && !app.isLoading && !app.noChanges && !app.isUpdating && !app.isDoneUpdating && !app.isErrorUpdating">
- <multiple-select id="app-roles"
- unique-data="{{$index}}"
- placeholder="Select roles"
- ng-model="app.appRoles"
- on-change="newUser.appChanged($index)"
- name-attr="roleName"
- value-attr="isApplied"></multiple-select>
- </div>
- <div id="app-item-no-contact" class="app-item-right-error" ng-show="app.isError">{{app.errorMessage}}</div>
- <div id="app-item-contacting" class="app-item-right-contacting" ng-show="app.isLoading">Contacting application...</div>
- <div id="app-item-no-changes" class="app-item-right-contacting" ng-show="app.noChanges">No changes</div>
- <div id="app-item-no-updating" class="app-item-right-contacting" ng-show="app.isUpdating">Updating application...</div>
- <div id="app-item-done-updating" class="app-item-right-contacting" ng-show="app.isDoneUpdating">Finished updating application</div>
- <div id="app-item-cannot-update" class="app-item-right-error" ng-show="app.isErrorUpdating">Could not update application...</div>
- <div id="app-item-delete" class="app-item-delete" ng-click="newUser.deleteApp(app)" ng-show="!app.isLoading && !app.isError"></div>
- <div id='ecomp-small-spinner' class="ecomp-small-spinner" ng-show="app.isLoading"></div>
- </div>
- </div>
-
- <div class="dialog-control">
- <span id="ecomp-save-spinner" class="ecomp-save-spinner" ng-show="newUser.isSaving || newUser.isGettingAdminApps"></span>
- <button id="new-user-back-button" class="btn btn-alt btn-small" ng-show="newUser.isShowBack" ng-click="newUser.navigateBack()">Back</button>
- <button id="new-user-save-button" class="btn btn-alt btn-small" ng-click="newUser.updateUserAppsRoles()"
- ng-disabled="(newUser.anyChanges == false)">Save
- </button>
- <button id="new-user-cancel-button" class="btn btn-alt btn-small" ng-click="closeThisDialog()">Cancel</button>
- </div>
-
- </div>
-
- </div>
-
-
-
-</div>
+<!-- + ================================================================================ + ECOMP Portal + ================================================================================ + Copyright (C) 2017 AT&T Intellectual Property + ================================================================================ + Licensed 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 class="new-user-modal"> + + <div class="search-users" ng-show="newUser.dialogState===1"> + + <search-users search-title="New User" + selected-user="newUser.selectedUser"></search-users> + + <div class="dialog-control"> + <button class="btn btn-alt btn-small" id="next-button" ng-click="newUser.selectedUser && newUser.getUserAppsRoles()" + ng-class="{disabled: !newUser.selectedUser}">Next + </button> + <button class="btn btn-alt btn-small" id="cancel-button" ng-click="closeThisDialog()">Cancel</button> + + </div> + </div> + + <div class="user-apps-roles" ng-show="newUser.dialogState===3"> + <div class="title" + ng-bind="newUser.selectedUser.firstName + ' ' + newUser.selectedUser.lastName + ' (' + newUser.selectedUser.orgUserId + ')'"></div> + + + <div class="app-roles-main"> + <div class="app-roles-main-title"> + <span class="left">Access and roles:</span> + </div> + + <div class="app-roles-list"> + <div class="app-item" ng-repeat="app in (newUser.adminApps) track by app.id" id="app-name-{{app.name.split(' ').join('-')}}" ng-show="!app.isDeleted"> + <div class="app-item-left" id="div-app-name-{{app.name.split(' ').join('-')}}">{{app.name | elipsis: 27}}</div> + <div class="app-item-right" id="div-app-name-dropdown-{{app.name.split(' ').join('-')}}" ng-show="!app.isError && !app.isLoading && !app.noChanges && !app.isUpdating && !app.isDoneUpdating && !app.isErrorUpdating"> + <multiple-select id="app-roles" + unique-data="{{$index}}" + placeholder="Select roles" + ng-model="app.appRoles" + on-change="newUser.appChanged($index)" + name-attr="roleName" + value-attr="isApplied"></multiple-select> + </div> + <div id="app-item-no-contact" class="app-item-right-error" ng-show="app.isError">{{app.errorMessage}}</div> + <div id="app-item-contacting" class="app-item-right-contacting" ng-show="app.isLoading">Contacting application...</div> + <div id="app-item-no-changes" class="app-item-right-contacting" ng-show="app.noChanges">No changes</div> + <div id="app-item-no-updating" class="app-item-right-contacting" ng-show="app.isUpdating">Updating application...</div> + <div id="app-item-done-updating" class="app-item-right-contacting" ng-show="app.isDoneUpdating">Finished updating application</div> + <div id="app-item-cannot-update" class="app-item-right-error" ng-show="app.isErrorUpdating">Could not update application...</div> + <div id="app-item-delete" class="app-item-delete" ng-click="newUser.deleteApp(app)" ng-show="!app.isLoading && !app.isError"></div> + <div id='ecomp-small-spinner' class="ecomp-small-spinner" ng-show="app.isLoading"></div> + </div> + </div> + + <div class="dialog-control"> + <span id="ecomp-save-spinner" class="ecomp-save-spinner" ng-show="newUser.isSaving || newUser.isGettingAdminApps"></span> + <button id="new-user-back-button" class="btn btn-alt btn-small" ng-show="newUser.isShowBack" ng-click="newUser.navigateBack()">Back</button> + <button id="new-user-save-button" class="btn btn-alt btn-small" ng-click="newUser.updateUserAppsRoles()" + ng-disabled="(newUser.anyChanges == false)">Save + </button> + <button id="new-user-cancel-button" class="btn btn-alt btn-small" ng-click="closeThisDialog()">Cancel</button> + </div> + + </div> + + </div> + + + +</div> + +<script> +$(document).ready(function(){ + $(".ngdialog-close").attr('id','dialog-close'); +}); +</script> diff --git a/ecomp-portal-FE-common/client/app/views/users/users.controller.js b/ecomp-portal-FE-common/client/app/views/users/users.controller.js index 1aa67601..ac223ed6 100644 --- a/ecomp-portal-FE-common/client/app/views/users/users.controller.js +++ b/ecomp-portal-FE-common/client/app/views/users/users.controller.js @@ -1,243 +1,244 @@ -/*-
- * ================================================================================
- * ECOMP Portal
- * ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property
- * ================================================================================
- * Licensed 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.
- * ================================================================================
- */
-'use strict';
-(function () {
- class UsersCtrl {
- constructor($log, applicationsService, usersService, confirmBoxService, $scope, ngDialog) {
- this.$log = $log;
- $scope.adminAppsIsNull = false;
- $scope.appsIsDown = false;
- $scope.noUsersInApp = false;
- $scope.multiAppAdmin = false;
-
- $log.info('UsersCtrl:: initializing...');
- /**
- * Handle all active HTTP requests
- * activeRequests @type {Array[requests with cancel option]}
- */
- let activeRequests = [];
- let clearReq = (req) => {
- activeRequests.splice(activeRequests.indexOf(req), 1);
- };
-
- let init = () => {
- this.isLoadingTable = false;
- this.selectedApp = null;
- this.isAppSelectDisabled = false;
- this.selectApp = 'Select application';
- this.adminApps = [{index: 0, id: 0, value: this.selectApp, title: this.selectApp}];
- getAdminApps();
-
- /*Table general configuration params*/
- this.searchString = '';
- /*Table data*/
- this.usersTableHeaders = ['First Name', 'Last Name', 'User ID', 'Roles'];
- this.accountUsers = [];
- };
-
- let getAdminApps = () => {
- $log.debug('UsersCtrl::getAdminApps: - Starting getAdminApps');
- try {
- this.isLoadingTable = true;
- let adminAppsReq = applicationsService.getAdminApps();
- adminAppsReq.promise().then(apps => {
- if (!apps || !apps.length) {
- $log.error('UsersCtrl::getAdminApps: - no apps found');
- return null;
- }
- $log.debug('UsersCtrl::getAdminApps: Apps for this user are: ' + JSON.stringify(apps));
- if (apps.length >= 2) {
- $log.info('UsersCtrl::getAdminApps: - more than one app for this admin:', apps.length, ' apps');
- $scope.multiAppAdmin = true;
- } else {
- this.adminApps = [] ;
- }
- let sortedApps = apps.sort(getSortOrder("name"));
- let realAppIndex = 1;
- for(let i=1; i<=sortedApps.length; i++){
- this.adminApps.push({
- index: realAppIndex,
- id: sortedApps[i - 1].id,
- value: sortedApps[i - 1].name,
- title: sortedApps[i - 1].name
- });
- realAppIndex = realAppIndex + 1;
- }
-
- $log.debug('UsersCtrl::getAdminApps: Apps for this user are: ' + JSON.stringify(this.adminApps));
-
- this.selectedApp = this.adminApps[0];
- clearReq(adminAppsReq);
- $scope.adminAppsIsNull = false;
- }).catch(e => {
- $scope.adminAppsIsNull = true;
- $log.error('UsersCtrl::getAdminApps: - getAdminApps() failed = '+ e.message);
- clearReq(adminAppsReq);
- confirmBoxService.showInformation('There was a problem retrieving the applications. ' +
- 'Please try again later.').then(isConfirmed => {});
-
- }).finally(() => {
- this.isLoadingTable = false;
- });
- } catch (e) {
- $scope.adminAppsIsNull = true;
- $log.error('UsersCtrl::getAdminApps: - getAdminApps() failed!');
- this.isLoadingTable = false;
- }
- };
-
- let getSortOrder = (prop) => {
- return function(a, b) {
- if (a[prop] > b[prop]) {
- return 1;
- } else if (a[prop] < b[prop]) {
- return -1;
- }
- return 0;
- }
- }
-
- this.updateUsersList = () => {
- $scope.appsIsDown = false;
- $scope.noUsersInApp = false;
- // $log.debug('UsersCtrl::updateUsersList: Starting updateUsersList');
- //reset search string
- this.searchString = '';
- //should i disable this too in case of moving between tabs?
- this.isAppSelectDisabled = true;
- //activate spinner
- this.isLoadingTable = true;
-
- if(this.adminApps!=null && this.selectedApp!=null){
- var tempSelected = null;
- for(let i=0; i<=this.adminApps.length; i++){
- if(typeof this.adminApps[i] != 'undefined' && this.selectedApp.value==this.adminApps[i].value){
- tempSelected=_.clone(this.adminApps[i]);
- }
- }
- if(tempSelected!=null){
- this.selectedApp= tempSelected;
- }
- }
-
- if (this.selectedApp.title != this.selectApp) { // 'Select Application'
- usersService.getAccountUsers(this.selectedApp.id)
- .then(accountUsers => {
- $log.debug('UsersCtrl::updateUsersList accountUsers: '+ accountUsers);
- if (angular.isObject(accountUsers)===false) {
- $log.error('UsersCtrl::updateUsersList accountUsers: App is down!');
- $scope.appsIsDown = true;
- }
- $log.debug('UsersCtrl::updateUsersList length: '+ Object.keys(accountUsers).length);
- this.isAppSelectDisabled = false;
- this.accountUsers = accountUsers;
- if (angular.isObject(accountUsers) && Object.keys(accountUsers).length === 0) {
- $log.debug('UsersCtrl::updateUsersList accountUsers: App has no users.');
- $scope.noUsersInApp = true;
- }
- }).catch(err => {
- this.isAppSelectDisabled = false;
- $log.error('UsersCtrl::updateUsersList error: ' + err);
- confirmBoxService.showInformation('There was a problem updating the users List. ' +
- 'Please try again later.').then(isConfirmed => {});
- $scope.appsIsDown = true;
- }).finally(() => {
- this.isLoadingTable = false;
- $scope.noAppSelected = false;
- });
- } else {
- // this.selectedApp = this.adminApps[0];
- this.isAppSelectDisabled = false;
- this.isLoadingTable = false;
- $scope.noUsersInApp = false;
- $scope.noAppSelected = true;
- }
- };
-
-
- this.openAddNewUserModal = (user) => {
- let data = null;
- if (user) {
- data = {
- dialogState: 3,
- selectedUser: {
- orgUserId: user.orgUserId,
- firstName: user.firstName,
- lastName: user.lastName
- }
- }
- }
- ngDialog.open({
- templateUrl: 'app/views/users/new-user-dialogs/new-user.modal.html',
- controller: 'NewUserModalCtrl',
- controllerAs: 'newUser',
- data: data
- }).closePromise.then(needUpdate => {
- if (needUpdate.value === true) {
- $log.debug('UsersCtrl::openAddNewUserModal updating table data...');
- this.updateUsersList();
- }
- });
- };
-
- this.openBulkUserUploadModal = (adminApps) => {
- let data = null;
- if (adminApps) {
- data = {
- dialogState: 3,
- selectedApplication: {
- appid: adminApps[0].appid,
- appName: adminApps[0].appName
- }
- }
- }
- ngDialog.open({
- templateUrl: 'app/views/users/new-user-dialogs/bulk-user.modal.html',
- controller: 'BulkUserModalCtrl',
- controllerAs: 'bulkUser',
- data: data
- }).closePromise.then(needUpdate => {
- this.updateUsersList();
- });
- };
-
-
- $scope.$watch('users.selectedApp.value', (newVal, oldVal) => {
- if (!newVal || _.isEqual(newVal, oldVal)) {
- return;
- }
- $log.debug('UsersCtrl::openAddNewUserModal:$watch selectedApp -> Fire with: ', newVal);
- this.accountUsers = []; //reset table and show swirl here
- this.updateUsersList();
- });
-
- $scope.$on('$destroy', () => {
- //cancel all active requests when closing the modal
- activeRequests.forEach(req => {
- req.cancel();
- });
- });
-
- init();
- }
- }
- UsersCtrl.$inject = ['$log', 'applicationsService', 'usersService', 'confirmBoxService', '$scope', 'ngDialog'];
- angular.module('ecompApp').controller('UsersCtrl', UsersCtrl);
-})();
+/*- + * ================================================================================ + * ECOMP Portal + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property + * ================================================================================ + * Licensed 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. + * ================================================================================ + */ +'use strict'; +(function () { + class UsersCtrl { + constructor($log, applicationsService, usersService, confirmBoxService, $scope, ngDialog) { + this.$log = $log; + $scope.adminAppsIsNull = false; + $scope.appsIsDown = false; + $scope.noUsersInApp = false; + $scope.multiAppAdmin = false; + + $log.info('UsersCtrl:: initializing...'); + /** + * Handle all active HTTP requests + * activeRequests @type {Array[requests with cancel option]} + */ + let activeRequests = []; + let clearReq = (req) => { + activeRequests.splice(activeRequests.indexOf(req), 1); + }; + + let init = () => { + this.isLoadingTable = false; + this.selectedApp = null; + this.isAppSelectDisabled = false; + this.selectApp = 'Select application'; + this.adminApps = [{index: 0, id: 0, value: this.selectApp, title: this.selectApp}]; + getAdminApps(); + + /*Table general configuration params*/ + this.searchString = ''; + /*Table data*/ + this.usersTableHeaders = ['First Name', 'Last Name', 'User ID', 'Roles']; + this.accountUsers = []; + }; + + let getAdminApps = () => { + $log.debug('UsersCtrl::getAdminApps: - Starting getAdminApps'); + try { + this.isLoadingTable = true; + let adminAppsReq = applicationsService.getAdminApps(); + adminAppsReq.promise().then(apps => { + if (!apps || !apps.length) { + $log.error('UsersCtrl::getAdminApps: - no apps found'); + return null; + } + $log.debug('UsersCtrl::getAdminApps: Apps for this user are: ' + JSON.stringify(apps)); + if (apps.length >= 2) { + $log.info('UsersCtrl::getAdminApps: - more than one app for this admin:', apps.length, ' apps'); + $scope.multiAppAdmin = true; + } else { + this.adminApps = [] ; + } + let sortedApps = apps.sort(getSortOrder("name")); + let realAppIndex = 1; + for(let i=1; i<=sortedApps.length; i++){ + this.adminApps.push({ + index: realAppIndex, + id: sortedApps[i - 1].id, + value: sortedApps[i - 1].name, + title: sortedApps[i - 1].name + }); + realAppIndex = realAppIndex + 1; + } + + $log.debug('UsersCtrl::getAdminApps: Apps for this user are: ' + JSON.stringify(this.adminApps)); + + this.selectedApp = this.adminApps[0]; + clearReq(adminAppsReq); + $scope.adminAppsIsNull = false; + }).catch(e => { + $scope.adminAppsIsNull = true; + $log.error('UsersCtrl::getAdminApps: - getAdminApps() failed = '+ e.message); + clearReq(adminAppsReq); + confirmBoxService.showInformation('There was a problem retrieving the applications. ' + + 'Please try again later.').then(isConfirmed => {}); + + }).finally(() => { + this.isLoadingTable = false; + }); + } catch (e) { + $scope.adminAppsIsNull = true; + $log.error('UsersCtrl::getAdminApps: - getAdminApps() failed!'); + this.isLoadingTable = false; + } + }; + + let getSortOrder = (prop) => { + return function(a, b) { + if (a[prop] > b[prop]) { + return 1; + } else if (a[prop] < b[prop]) { + return -1; + } + return 0; + } + } + + this.updateUsersList = () => { + $scope.appsIsDown = false; + $scope.noUsersInApp = false; + // $log.debug('UsersCtrl::updateUsersList: Starting updateUsersList'); + //reset search string + this.searchString = ''; + //should i disable this too in case of moving between tabs? + this.isAppSelectDisabled = true; + //activate spinner + this.isLoadingTable = true; + + if(this.adminApps!=null && this.selectedApp!=null){ + var tempSelected = null; + for(let i=0; i<=this.adminApps.length; i++){ + if(typeof this.adminApps[i] != 'undefined' && this.selectedApp.value==this.adminApps[i].value){ + tempSelected=_.clone(this.adminApps[i]); + } + } + if(tempSelected!=null){ + this.selectedApp= tempSelected; + } + } + + if (this.selectedApp.title != this.selectApp) { // 'Select Application' + usersService.getAccountUsers(this.selectedApp.id) + .then(accountUsers => { + $log.debug('UsersCtrl::updateUsersList accountUsers: '+ accountUsers); + if (angular.isObject(accountUsers)===false) { + $log.error('UsersCtrl::updateUsersList accountUsers: App is down!'); + $scope.appsIsDown = true; + } + $log.debug('UsersCtrl::updateUsersList length: '+ Object.keys(accountUsers).length); + this.isAppSelectDisabled = false; + this.accountUsers = accountUsers; + if (angular.isObject(accountUsers) && Object.keys(accountUsers).length === 0) { + $log.debug('UsersCtrl::updateUsersList accountUsers: App has no users.'); + $scope.noUsersInApp = true; + } + }).catch(err => { + this.isAppSelectDisabled = false; + $log.error('UsersCtrl::updateUsersList error: ' + err); + confirmBoxService.showInformation('There was a problem updating the users List. ' + + 'Please try again later.').then(isConfirmed => {}); + $scope.appsIsDown = true; + }).finally(() => { + this.isLoadingTable = false; + $scope.noAppSelected = false; + }); + } else { + // this.selectedApp = this.adminApps[0]; + this.isAppSelectDisabled = false; + this.isLoadingTable = false; + $scope.noUsersInApp = false; + $scope.noAppSelected = true; + } + }; + + + this.openAddNewUserModal = (user) => { + let data = null; + if (user) { + data = { + dialogState: 3, + selectedUser: { + orgUserId: user.orgUserId, + firstName: user.firstName, + lastName: user.lastName, + + } + } + } + ngDialog.open({ + templateUrl: 'app/views/users/new-user-dialogs/new-user.modal.html', + controller: 'NewUserModalCtrl', + controllerAs: 'newUser', + data: data + }).closePromise.then(needUpdate => { + if (needUpdate.value === true) { + $log.debug('UsersCtrl::openAddNewUserModal updating table data...'); + this.updateUsersList(); + } + }); + }; + + this.openBulkUserUploadModal = (adminApps) => { + let data = null; + if (adminApps) { + data = { + dialogState: 3, + selectedApplication: { + appid: adminApps[0].appid, + appName: adminApps[0].appName + } + } + } + ngDialog.open({ + templateUrl: 'app/views/users/new-user-dialogs/bulk-user.modal.html', + controller: 'BulkUserModalCtrl', + controllerAs: 'bulkUser', + data: data + }).closePromise.then(needUpdate => { + this.updateUsersList(); + }); + }; + + + $scope.$watch('users.selectedApp.value', (newVal, oldVal) => { + if (!newVal || _.isEqual(newVal, oldVal)) { + return; + } + $log.debug('UsersCtrl::openAddNewUserModal:$watch selectedApp -> Fire with: ', newVal); + this.accountUsers = []; //reset table and show swirl here + this.updateUsersList(); + }); + + $scope.$on('$destroy', () => { + //cancel all active requests when closing the modal + activeRequests.forEach(req => { + req.cancel(); + }); + }); + + init(); + } + } + UsersCtrl.$inject = ['$log', 'applicationsService', 'usersService', 'confirmBoxService', '$scope', 'ngDialog']; + angular.module('ecompApp').controller('UsersCtrl', UsersCtrl); +})(); diff --git a/ecomp-portal-FE-common/client/app/views/users/users.controller.spec.js b/ecomp-portal-FE-common/client/app/views/users/users.controller.spec.js index 96231163..0b3c0110 100644 --- a/ecomp-portal-FE-common/client/app/views/users/users.controller.spec.js +++ b/ecomp-portal-FE-common/client/app/views/users/users.controller.spec.js @@ -1,141 +1,141 @@ -/*-
- * ================================================================================
- * ECOMP Portal
- * ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property
- * ================================================================================
- * Licensed 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.
- * ================================================================================
- */
-// /**
-// * Created by nnaffar on 12/17/15.
-// */
-// 'use strict';
-//
-// describe('Controller: UsersCtrl ', () => {
-// beforeEach(module('ecompApp'));
-//
-// //destroy $http default cache before starting to prevent the error 'default cache already exists'
-// beforeEach(inject((_CacheFactory_)=> {
-// _CacheFactory_.destroyAll();
-// }));
-//
-// let users, $controller, $q, $rootScope, $log, $scope;
-//
-// beforeEach(inject((_$controller_, _$q_, _$rootScope_, _$log_)=> {
-// [$controller, $q, $rootScope, $log] = [_$controller_, _$q_, _$rootScope_, _$log_];
-// }));
-//
-// let applicationsServiceMock, usersServiceMock;
-// let deferredAdminApps, deferredUsersAccounts;
-// beforeEach(()=> {
-// [deferredAdminApps, deferredUsersAccounts] = [$q.defer(), $q.defer()];
-//
-// applicationsServiceMock = {
-// getAdminApps: () => {
-// var promise = () => {return deferredAdminApps.promise};
-// var cancel = jasmine.createSpy();
-// return {
-// promise: promise,
-// cancel: cancel
-// }
-// }
-// };
-//
-// usersServiceMock = jasmine.createSpyObj('usersServiceMock', ['getAccountUsers']);
-//
-// //applicationsServiceMock.getAdminApps().promise().and.returnValue(deferredAdminApps.promise);
-// usersServiceMock.getAccountUsers.and.returnValue(deferredUsersAccounts.promise);
-//
-// $scope = $rootScope.$new();
-// users = $controller('UsersCtrl', {
-// $log: $log,
-// applicationsService: applicationsServiceMock,
-// usersService: usersServiceMock,
-// $scope: $scope
-// });
-// $scope.users = users;
-// });
-//
-// //MOCKS
-// let appsListMock = [
-// {value: 'SSP', title: 'SSP', id: 3},
-// {value: 'ASDC', title: 'ASDC', id: 23},
-// {value: 'Formation', title: 'Formation', id: 223}
-// ];
-//
-// let usersListMock = [
-// {
-// "orgUserId": "nn605g",
-// "firstName": "Nabil",
-// "lastName": "Naffar",
-// "roles": [
-// {
-// "roleId": 1,
-// "roleName": "Standard user"
-// },
-// {
-// "roleId": 9,
-// "roleName": "Super standard user"
-// },
-// {
-// "roleId": 2,
-// "roleName": "Super duper standard user"
-// }
-// ]
-// }];
-// let secondUsersListMock = [
-// {
-// "orgUserId": "sadf7",
-// "firstName": "John",
-// "lastName": "Hall",
-// "roles": [
-// {
-// "roleId": 1,
-// "roleName": "Standard user"
-// },
-// {
-// "roleId": 2,
-// "roleName": "Super duper standard user"
-// }
-// ]
-// }];
-//
-// it('should get all user\'s administrated applications when initializing the view', ()=> {
-// deferredAdminApps.resolve(appsListMock);
-// deferredUsersAccounts.resolve(usersListMock);
-// $scope.$apply();
-// expect(users.adminApps).toEqual(appsListMock);
-// expect(users.selectedApp).toEqual(appsListMock[0]);
-// });
-//
-// it('should get first application users by default when initializing the view', () => {
-// $scope.$apply();
-// deferredAdminApps.resolve(appsListMock);
-// deferredUsersAccounts.resolve(usersListMock);
-// $scope.$apply();
-// expect(users.accountUsers).toEqual(usersListMock);
-// });
-//
-// it('should get application users when changing application', () => {
-// $scope.$apply();
-// deferredAdminApps.resolve(appsListMock);
-// $scope.$apply();
-//
-// users.selectedApp = appsListMock[1];
-// deferredUsersAccounts.resolve(secondUsersListMock);
-// $scope.$apply('users');//change app
-//
-// expect(users.accountUsers).toEqual(secondUsersListMock);
-// });
-// });
+/*- + * ================================================================================ + * ECOMP Portal + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property + * ================================================================================ + * Licensed 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. + * ================================================================================ + */ +// /** +// * Created by nnaffar on 12/17/15. +// */ +// 'use strict'; +// +// describe('Controller: UsersCtrl ', () => { +// beforeEach(module('ecompApp')); +// +// //destroy $http default cache before starting to prevent the error 'default cache already exists' +// beforeEach(inject((_CacheFactory_)=> { +// _CacheFactory_.destroyAll(); +// })); +// +// let users, $controller, $q, $rootScope, $log, $scope; +// +// beforeEach(inject((_$controller_, _$q_, _$rootScope_, _$log_)=> { +// [$controller, $q, $rootScope, $log] = [_$controller_, _$q_, _$rootScope_, _$log_]; +// })); +// +// let applicationsServiceMock, usersServiceMock; +// let deferredAdminApps, deferredUsersAccounts; +// beforeEach(()=> { +// [deferredAdminApps, deferredUsersAccounts] = [$q.defer(), $q.defer()]; +// +// applicationsServiceMock = { +// getAdminApps: () => { +// var promise = () => {return deferredAdminApps.promise}; +// var cancel = jasmine.createSpy(); +// return { +// promise: promise, +// cancel: cancel +// } +// } +// }; +// +// usersServiceMock = jasmine.createSpyObj('usersServiceMock', ['getAccountUsers']); +// +// //applicationsServiceMock.getAdminApps().promise().and.returnValue(deferredAdminApps.promise); +// usersServiceMock.getAccountUsers.and.returnValue(deferredUsersAccounts.promise); +// +// $scope = $rootScope.$new(); +// users = $controller('UsersCtrl', { +// $log: $log, +// applicationsService: applicationsServiceMock, +// usersService: usersServiceMock, +// $scope: $scope +// }); +// $scope.users = users; +// }); +// +// //MOCKS +// let appsListMock = [ +// {value: 'SSP', title: 'SSP', id: 3}, +// {value: 'ASDC', title: 'ASDC', id: 23}, +// {value: 'Formation', title: 'Formation', id: 223} +// ]; +// +// let usersListMock = [ +// { +// "orgUserId": "nn605g", +// "firstName": "Nabil", +// "lastName": "Naffar", +// "roles": [ +// { +// "roleId": 1, +// "roleName": "Standard user" +// }, +// { +// "roleId": 9, +// "roleName": "Super standard user" +// }, +// { +// "roleId": 2, +// "roleName": "Super duper standard user" +// } +// ] +// }]; +// let secondUsersListMock = [ +// { +// "orgUserId": "sadf7", +// "firstName": "John", +// "lastName": "Hall", +// "roles": [ +// { +// "roleId": 1, +// "roleName": "Standard user" +// }, +// { +// "roleId": 2, +// "roleName": "Super duper standard user" +// } +// ] +// }]; +// +// it('should get all user\'s administrated applications when initializing the view', ()=> { +// deferredAdminApps.resolve(appsListMock); +// deferredUsersAccounts.resolve(usersListMock); +// $scope.$apply(); +// expect(users.adminApps).toEqual(appsListMock); +// expect(users.selectedApp).toEqual(appsListMock[0]); +// }); +// +// it('should get first application users by default when initializing the view', () => { +// $scope.$apply(); +// deferredAdminApps.resolve(appsListMock); +// deferredUsersAccounts.resolve(usersListMock); +// $scope.$apply(); +// expect(users.accountUsers).toEqual(usersListMock); +// }); +// +// it('should get application users when changing application', () => { +// $scope.$apply(); +// deferredAdminApps.resolve(appsListMock); +// $scope.$apply(); +// +// users.selectedApp = appsListMock[1]; +// deferredUsersAccounts.resolve(secondUsersListMock); +// $scope.$apply('users');//change app +// +// expect(users.accountUsers).toEqual(secondUsersListMock); +// }); +// }); diff --git a/ecomp-portal-FE-common/client/app/views/users/users.less b/ecomp-portal-FE-common/client/app/views/users/users.less index 7a0e9ebb..4c38b33c 100644 --- a/ecomp-portal-FE-common/client/app/views/users/users.less +++ b/ecomp-portal-FE-common/client/app/views/users/users.less @@ -1,25 +1,30 @@ .users-page-main{ - .bg_portalWhite;//white for 1702 - //.bg_portalGray; // gray for 1610 - position: @page-main-position; - top: @page-main-top; - left: @page-main-left; - right: @page-main-right; - bottom: @page-main-bottom; - padding-top: @padding-top; - overflow-y: @page-main-overflow-y; - padding-left: @padding-left-side; -#input-table-search::-webkit-input-placeholder, -{ -font-style: italic; - color: #D7D7D7; -} + .bg_portalWhite;//white for 1702 + //.bg_portalGray; // gray for 1610 + position: @page-main-position; + top: @page-main-top; + left: @page-main-left; + right: @page-main-right; + bottom: @page-main-bottom; + padding-top: @padding-top; + overflow-y: @page-main-overflow-y; + padding-left: @padding-left-side; + #input-table-search::-webkit-input-placeholder, + { + font-style: italic; + color: #D7D7D7; + } .users-table { - width: @table-width; - //margin-left: @table-margin-left; - margin: 0 auto; - + width: @table-width; + //margin-left: @table-margin-left; + margin: 0 auto; } + + .table-users-div{ + width:15px; + font-size:23px; + cursor: pointer; + } .error-text { width: 1170px; diff --git a/ecomp-portal-FE-common/client/app/views/users/users.tpl.html b/ecomp-portal-FE-common/client/app/views/users/users.tpl.html index ff3edde0..606ced6e 100644 --- a/ecomp-portal-FE-common/client/app/views/users/users.tpl.html +++ b/ecomp-portal-FE-common/client/app/views/users/users.tpl.html @@ -1,98 +1,98 @@ -<!--
- ================================================================================
- ECOMP Portal
- ================================================================================
- Copyright (C) 2017 AT&T Intellectual Property
- ================================================================================
- Licensed 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 class="w-ecomp-main">
- <div class="w-ecomp-main-container" >
- <div class="users-page-main" id="page-content">
- <div id="users-page-title" class="w-ecomp-main-view-title">
- <h1 class="heading-page" >Users</h1>
- </div>
- <div class="users-table">
- <div class="table-control">
- <div class="table-control-fields">
- <div class="table-dropdown">
- <select id="dropdown1" name="dropdown1" b2b-dropdown placeholder-text="Select Application" ng-model="users.selectedApp.value">
- <option b2b-dropdown-list option-repeat="d in users.adminApps" value="{{d.value}}">{{d.title}}</option>
- </select>
- </div>
- <div>
- <input id="input-table-search" placeholder="Search" class="table-search-field" type="text" data-ng-model="users.searchString">
- </div>
- <button class="btn btn-alt btn-small" ng-click="users.openAddNewUserModal()"><i class="icon-people-userbookmark" aria-hidden="true"></i> Add User</button>
- <button class="btn btn-alt btn-small" ng-click="users.openBulkUserUploadModal()"><i class="icon-arrows-upload" aria-hidden="true"></i> Bulk Upload</button>
- </div>
- </div>
- <div ng-hide="users.isLoadingTable">
- <div class="error-text" id="div-select-app" ng-show="noAppSelected">
- <p class="error-help">Use the 'Select application' dropdown to see users.</p>
- </div>
- <div class="error-text"
- id="div-error-no-users"
- ng-show="noUsersInApp">
- <p> </p>
- <p class="error-help">
- No users found. Select "Add User" to add a User to the application.
- </p>
- </div>
- <div class="error-text"
- id="div-error-app-down"
- ng-show="appsIsDown" >
- <p> </p>
- <p class="error-help">
- Failed to communicate with the application.
- Please try again later or contact a system administrator.
- </p>
- </div>
- </div>
- <span class="ecomp-spinner" ng-show="users.isLoadingTable"></span>
- <div b2b-table table-data="users.accountUsers" ng-hide="users.isLoadingTable" search-string="users.searchString" class="b2b-table-div">
- <table>
- <thead b2b-table-row type="header">
- <tr >
- <th b2b-table-header key="firstName" sortable="true" id="col1">First Name</th>
- <th b2b-table-header key="lastName" sortable="true" id="col2">Last Name</th>
- <th b2b-table-header key="orgUserId" sortable="true" id="col3">User ID</th>
- <th b2b-table-header key="" sortable="falses" id="col4">Roles</th>
- </tr>
- </thead>
- <tbody b2b-table-row type="body" row-repeat="rowData in users.accountUsers">
- <tr ng-click="users.openAddNewUserModal(rowData)">
- <td b2b-table-body id="rowheader_t1_{{$index}}" headers="col1" ng-bind="rowData.firstName"></td>
- <td b2b-table-body headers="rowheader_t1_{{$index}} col2" ng-bind="rowData.lastName"></td>
- <td b2b-table-body headers="rowheader_t1_{{$index}} col3" ng-bind="rowData.orgUserId"></td>
- <td b2b-table-body headers="rowheader_t1_{{$index}} col4">
- <div class="ecomp-table-repeat" ng-repeat="role in rowData.roles" ng-bind="role.name"></div>
- </td>
- </tr>
- </tbody>
- </table>
- </div>
- </div>
- <div class="error-text" id="div-error-403" ng-show="adminAppsIsNull==true">
- <h1>Attention:</h1>
- <p> </p>
- <p class="error-help">It appears that you have not been added as an admin yet to an application.</p>
- <p> </p>
- <p class="error-help">Click on the Admins link to the left and check and see if you are listed as an admin for an application.
- If not, you can add yourself to the appropriate application.</p>
- </div>
- </div>
- </div>
-
-</div>
+<!-- + ================================================================================ + ECOMP Portal + ================================================================================ + Copyright (C) 2017 AT&T Intellectual Property + ================================================================================ + Licensed 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 class="w-ecomp-main"> + <div class="w-ecomp-main-container" > + <div class="users-page-main" id="page-content"> + <div id="users-page-title" class="w-ecomp-main-view-title"> + <h1 class="heading-page" >Users</h1> + </div> + <div class="users-table"> + <div class="table-control"> + <div class="table-control-fields"> + <div class="table-dropdown"> + <select id="dropdown1" name="dropdown1" b2b-dropdown placeholder-text="Select Application" ng-model="users.selectedApp.value"> + <option b2b-dropdown-list option-repeat="d in users.adminApps" value="{{d.value}}">{{d.title}}</option> + </select> + </div> + <div> + <input id="input-table-search" placeholder="Search" class="table-search-field" type="text" data-ng-model="users.searchString"> + </div> + <button class="btn btn-alt btn-small" ng-click="users.openAddNewUserModal()"><i class="icon-people-userbookmark" aria-hidden="true"></i> Add User</button> + <button class="btn btn-alt btn-small" ng-click="users.openBulkUserUploadModal()"><i class="icon-arrows-upload" aria-hidden="true"></i> Bulk Upload</button> + </div> + </div> + <div ng-hide="users.isLoadingTable"> + <div class="error-text" id="div-select-app" ng-show="noAppSelected"> + <p class="error-help">Use the 'Select application' dropdown to see users.</p> + </div> + <div class="error-text" + id="div-error-no-users" + ng-show="noUsersInApp"> + <p> </p> + <p class="error-help"> + No users found. Select "Add User" to add a User to the application. + </p> + </div> + <div class="error-text" + id="div-error-app-down" + ng-show="appsIsDown" > + <p> </p> + <p class="error-help"> + Failed to communicate with the application. + Please try again later or contact a system administrator. + </p> + </div> + </div> + <span class="ecomp-spinner" ng-show="users.isLoadingTable"></span> + <div b2b-table table-data="users.accountUsers" ng-hide="users.isLoadingTable" search-string="users.searchString" class="b2b-table-div"> + <table> + <thead b2b-table-row type="header"> + <tr > + <th b2b-table-header key="firstName" sortable="true" id="col1" default-sort="a">First Name</th> + <th b2b-table-header key="lastName" sortable="true" id="col2">Last Name</th> + <th b2b-table-header key="orgUserId" sortable="true" id="col3">User ID</th> + <th b2b-table-header key="" sortable="falses" id="col4">Roles</th> + </tr> + </thead> + <tbody b2b-table-row type="body" row-repeat="rowData in users.accountUsers" class="table-users-div"> + <tr ng-click="users.openAddNewUserModal(rowData)"> + <td b2b-table-body id="rowheader_t1_{{$index}}" headers="col1" ng-bind="rowData.firstName"></td> + <td b2b-table-body headers="rowheader_t1_{{$index}} col2" ng-bind="rowData.lastName"></td> + <td b2b-table-body headers="rowheader_t1_{{$index}} col3" ng-bind="rowData.orgUserId"></td> + <td b2b-table-body headers="rowheader_t1_{{$index}} col4"> + <div class="ecomp-table-repeat" ng-repeat="role in rowData.roles" ng-bind="role.name"></div> + </td> + </tr> + </tbody> + </table> + </div> + </div> + <div class="error-text" id="div-error-403" ng-show="adminAppsIsNull==true"> + <h1>Attention:</h1> + <p> </p> + <p class="error-help">It appears that you have not been added as an admin yet to an application.</p> + <p> </p> + <p class="error-help">Click on the Admins link to the left and check and see if you are listed as an admin for an application. + If not, you can add yourself to the appropriate application.</p> + </div> + </div> + </div> + +</div> |