From 627badaf69987c01811c477219fd943757a635f5 Mon Sep 17 00:00:00 2001 From: "Christopher Lott (Christopher) (cl778h)" Date: Mon, 12 Jun 2017 09:49:00 -0400 Subject: [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) --- .../applications/applications.controller.spec.js | 38 +- .../src/views/applications/applications.tpl.html | 4 +- .../add-catalog-dialogs/new-catalog.controller.js | 436 +++++------ .../add-catalog-dialogs/new-catalog.modal.html | 226 +++--- .../views/dashboard/dashboard-extension.tpl.html | 1 + .../client/src/views/dashboard/dashboard.tpl.html | 173 ----- .../client/src/views/footer/footer.controller.js | 96 +-- .../src/views/footer/footer.controller.spec.js | 38 +- .../client/src/views/footer/footer.less | 208 +++--- .../client/src/views/footer/footer.tpl.html | 68 +- .../menu-details.controller.js | 830 ++++++++++----------- .../menu-details.delete.modal.html | 74 +- .../functionalMenu-dialog/menu-details.modal.html | 206 ++--- .../functionalMenu/functionalMenu.controller.js | 744 +++++++++--------- .../views/functionalMenu/functionalMenu.tpl.html | 92 +-- .../src/views/functionalMenu/jqTreeContextMenu.js | 428 +++++------ .../src/views/header/header-extension.tpl.html | 3 + .../client/src/views/header/header-logo.html | 1 + .../profile-edit.controller.js | 87 +++ .../profile-edit-dialogs/profile-edit.modal.html | 69 ++ .../profile-edit-dialogs/profile-edit.modal.less | 21 + .../client/src/views/search/search.controller.js | 396 +++++----- .../src/views/search/search.controller.spec.js | 38 +- .../views/support/contact-us/contact-us.aux.html | 50 +- .../views/support/get-access/get-accessinfo.html | 48 +- .../client/src/views/userbar/userbar.tpl.html | 40 +- 26 files changed, 2212 insertions(+), 2203 deletions(-) create mode 100644 ecomp-portal-FE-os/client/src/views/dashboard/dashboard-extension.tpl.html delete mode 100644 ecomp-portal-FE-os/client/src/views/dashboard/dashboard.tpl.html create mode 100644 ecomp-portal-FE-os/client/src/views/header/header-extension.tpl.html create mode 100644 ecomp-portal-FE-os/client/src/views/header/header-logo.html create mode 100644 ecomp-portal-FE-os/client/src/views/header/profile-edit-dialogs/profile-edit.controller.js create mode 100644 ecomp-portal-FE-os/client/src/views/header/profile-edit-dialogs/profile-edit.modal.html create mode 100644 ecomp-portal-FE-os/client/src/views/header/profile-edit-dialogs/profile-edit.modal.less (limited to 'ecomp-portal-FE-os/client/src/views') diff --git a/ecomp-portal-FE-os/client/src/views/applications/applications.controller.spec.js b/ecomp-portal-FE-os/client/src/views/applications/applications.controller.spec.js index 3841a2b3..32cc3a1f 100644 --- a/ecomp-portal-FE-os/client/src/views/applications/applications.controller.spec.js +++ b/ecomp-portal-FE-os/client/src/views/applications/applications.controller.spec.js @@ -1,19 +1,19 @@ -/*- - * ================================================================================ - * 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. - * ================================================================================ - */ +/*- + * ================================================================================ + * 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. + * ================================================================================ + */ diff --git a/ecomp-portal-FE-os/client/src/views/applications/applications.tpl.html b/ecomp-portal-FE-os/client/src/views/applications/applications.tpl.html index edded4bb..fa61e554 100644 --- a/ecomp-portal-FE-os/client/src/views/applications/applications.tpl.html +++ b/ecomp-portal-FE-os/client/src/views/applications/applications.tpl.html @@ -42,7 +42,7 @@ - + @@ -78,4 +78,4 @@ - \ No newline at end of file + diff --git a/ecomp-portal-FE-os/client/src/views/catalog/add-catalog-dialogs/new-catalog.controller.js b/ecomp-portal-FE-os/client/src/views/catalog/add-catalog-dialogs/new-catalog.controller.js index 5372841e..c2eda6ed 100644 --- a/ecomp-portal-FE-os/client/src/views/catalog/add-catalog-dialogs/new-catalog.controller.js +++ b/ecomp-portal-FE-os/client/src/views/catalog/add-catalog-dialogs/new-catalog.controller.js @@ -1,218 +1,218 @@ -/*- - * ================================================================================ - * 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 NewCatalogModalCtrl { - constructor($scope, $log, usersService, catalogService, applicationsService, confirmBoxService) { - let init = () => { - //$log.info('NewUserModalCtrl::init'); - this.isSaving = false; - this.adminApps =[]; - this.appRoles = []; - $scope.userAppRoles = []; - $scope.titleText = "Request for Access in MyLogins:"; - $scope.title ="Request is pending in MyLogins for the following Roles"; - 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 === 2){ - this.getUserAppsRoles(); - } - } - }; - - 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 = () => { - - //$log.debug('NewUserModalCtrl::getUserAppsRoles: about to call getAdminAppsSimpler'); - this.isGettingAdminApps = true; - catalogService.getAppCatalog().then((apps) => { - //$log.debug('NewUserModalCtrl::getUserAppsRoles: beginning of then for getAdminAppsSimpler'); - - this.isGettingAdminApps = false; - if (!apps || !apps.length) { - $log.error('NewUserModalCtrl::getUserApps error: no admin apps found'); - return null; - } - //$log.debug('NewUserModalCtrl::getUserAppsRoles: then for getAdminAppsSimpler: step 2'); - //$log.debug('NewUserModalCtrl::getUserAppsRoles: admin apps: ', apps); - - this.dialogState = 2; - this.isLoading = true; - this.adminApps = apps; - - catalogService.getuserAppRolesCatalog(this.selectedUser.headerText).then( - function(result) { - // $log.debug('CatalogCtrl:storeSelection result is ', result); - - $scope.userAppRoles = result; - $scope.displyUserAppCatalogRoles = true; - if(result.length === 1 && result[0].requestedRoleId === null) - { - $scope.title= "Removal Request is pending in MyLogins"; - } - - if($scope.userAppRoles.length==0) - { - $scope.displyUserAppCatalogRoles = false; - } - }); - apps.forEach(app => { - if(app.name === this.selectedUser.headerText){ - //$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.attuid).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.attuid || !this.adminApps){ - $log.error('NewUserModalCtrl::updateUserAppsRoles: mmissing arguments'); - return; - } - this.isSaving = true; - confirmBoxService.makeUserAppRoleCatalogChanges('Are you sure you want to make these changes?') - .then(confirmed => { - if(confirmed === true){ - //$log.debug('NewUserModalCtrl::updateUserAppsRoles: going to update user: ' + this.selectedUser.attuid); - 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 UserAppRolesRequest = { - attuid: this.selectedUser.attuid, - appId: app.id, - appRoles: app.appRoles, - appName: app.name - }; - this.isSaving = true; - $log.debug('going to update user: ' + this.selectedUser.attuid + ' with app roles: ' + JSON.stringify(this.adminAppsRoles)); - applicationsService.saveUserAppsRoles(UserAppRolesRequest).then(res => { - app.isUpdating = false; - $scope.closeThisDialog(true); - }).catch(err => { - $log.error('NewAdminModalCtrl.updateAdminAppsRoles:: Failed - ' + err); - }).finally(()=> { - this.isSaving = false; - }) - } - }); - }else{ - this.isSaving = false; - } - - - - }); - - }; - - /** - * 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(); - }); - } - } - NewCatalogModalCtrl.$inject = ['$scope', '$log', 'usersService', 'catalogService', 'applicationsService', 'confirmBoxService']; - angular.module('ecompApp').controller('NewCatalogModalCtrl', NewCatalogModalCtrl); -})(); +/*- + * ================================================================================ + * 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 NewCatalogModalCtrl { + constructor($scope, $log, usersService, catalogService, applicationsService, confirmBoxService) { + let init = () => { + //$log.info('NewUserModalCtrl::init'); + this.isSaving = false; + this.adminApps =[]; + this.appRoles = []; + $scope.userAppRoles = []; + $scope.titleText = "Request for Access in MyLogins:"; + $scope.title ="Request is pending in MyLogins for the following Roles"; + 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 === 2){ + this.getUserAppsRoles(); + } + } + }; + + 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 = () => { + + //$log.debug('NewUserModalCtrl::getUserAppsRoles: about to call getAdminAppsSimpler'); + this.isGettingAdminApps = true; + catalogService.getAppCatalog().then((apps) => { + //$log.debug('NewUserModalCtrl::getUserAppsRoles: beginning of then for getAdminAppsSimpler'); + + this.isGettingAdminApps = false; + if (!apps || !apps.length) { + $log.error('NewUserModalCtrl::getUserApps error: no admin apps found'); + return null; + } + //$log.debug('NewUserModalCtrl::getUserAppsRoles: then for getAdminAppsSimpler: step 2'); + //$log.debug('NewUserModalCtrl::getUserAppsRoles: admin apps: ', apps); + + this.dialogState = 2; + this.isLoading = true; + this.adminApps = apps; + + catalogService.getuserAppRolesCatalog(this.selectedUser.headerText).then( + function(result) { + // $log.debug('CatalogCtrl:storeSelection result is ', result); + + $scope.userAppRoles = result; + $scope.displyUserAppCatalogRoles = true; + if(result.length === 1 && result[0].requestedRoleId === null) + { + $scope.title= "Removal Request is pending in MyLogins"; + } + + if($scope.userAppRoles.length==0) + { + $scope.displyUserAppCatalogRoles = false; + } + }); + apps.forEach(app => { + if(app.name === this.selectedUser.headerText){ + //$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.attuid).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.attuid || !this.adminApps){ + $log.error('NewUserModalCtrl::updateUserAppsRoles: mmissing arguments'); + return; + } + this.isSaving = true; + confirmBoxService.makeUserAppRoleCatalogChanges('Are you sure you want to make these changes?') + .then(confirmed => { + if(confirmed === true){ + //$log.debug('NewUserModalCtrl::updateUserAppsRoles: going to update user: ' + this.selectedUser.attuid); + 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 UserAppRolesRequest = { + attuid: this.selectedUser.attuid, + appId: app.id, + appRoles: app.appRoles, + appName: app.name + }; + this.isSaving = true; + $log.debug('going to update user: ' + this.selectedUser.attuid + ' with app roles: ' + JSON.stringify(this.adminAppsRoles)); + applicationsService.saveUserAppsRoles(UserAppRolesRequest).then(res => { + app.isUpdating = false; + $scope.closeThisDialog(true); + }).catch(err => { + $log.error('NewAdminModalCtrl.updateAdminAppsRoles:: Failed - ' + err); + }).finally(()=> { + this.isSaving = false; + }) + } + }); + }else{ + this.isSaving = false; + } + + + + }); + + }; + + /** + * 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(); + }); + } + } + NewCatalogModalCtrl.$inject = ['$scope', '$log', 'usersService', 'catalogService', 'applicationsService', 'confirmBoxService']; + angular.module('ecompApp').controller('NewCatalogModalCtrl', NewCatalogModalCtrl); +})(); diff --git a/ecomp-portal-FE-os/client/src/views/catalog/add-catalog-dialogs/new-catalog.modal.html b/ecomp-portal-FE-os/client/src/views/catalog/add-catalog-dialogs/new-catalog.modal.html index 1cf96f7f..3578cc09 100644 --- a/ecomp-portal-FE-os/client/src/views/catalog/add-catalog-dialogs/new-catalog.modal.html +++ b/ecomp-portal-FE-os/client/src/views/catalog/add-catalog-dialogs/new-catalog.modal.html @@ -1,113 +1,113 @@ - -
- -
-
-
{{titleText}}
-
-
-
- -
-
-
{{app.name - | elipsis: 27}}
-
- -
- -
- -
- - -
{{app.errorMessage | elipsis: 35}}
-
Contacting - application...
-
No - changes
-
Updating - application...
-
Finished updating application
-
Could - not update application...
-
-
- -   - -
-
{{title}}
-   -
-
- -
- - {{getUserApplicationRole.rolename}} -
- -
-
- -
-
- -
- - -
Cancel
-
- -
- -
- -
+ +
+ +
+
+
{{titleText}}
+
+
+
+ +
+
+
{{app.name + | elipsis: 27}}
+
+ +
+ +
+ +
+ + +
{{app.errorMessage | elipsis: 35}}
+
Contacting + application...
+
No + changes
+
Updating + application...
+
Finished updating application
+
Could + not update application...
+
+
+ +   + +
+
{{title}}
+   +
+
+ +
+ + {{getUserApplicationRole.rolename}} +
+ +
+
+ +
+
+ +
+ + +
Cancel
+
+ +
+ +
+ +
diff --git a/ecomp-portal-FE-os/client/src/views/dashboard/dashboard-extension.tpl.html b/ecomp-portal-FE-os/client/src/views/dashboard/dashboard-extension.tpl.html new file mode 100644 index 00000000..aae5519f --- /dev/null +++ b/ecomp-portal-FE-os/client/src/views/dashboard/dashboard-extension.tpl.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/ecomp-portal-FE-os/client/src/views/dashboard/dashboard.tpl.html b/ecomp-portal-FE-os/client/src/views/dashboard/dashboard.tpl.html deleted file mode 100644 index cf5c2ee6..00000000 --- a/ecomp-portal-FE-os/client/src/views/dashboard/dashboard.tpl.html +++ /dev/null @@ -1,173 +0,0 @@ - -
-
- -
-
-
- Applications Sort by: - -
- -
- -
-
-
-
-
-
-
- You do not have access to any application or function in ECOMP - Portal. -
-
-
- -
-
    -
  • -
    -
    - -

    {{item.headerText | - elipsis: 14}}

    -
    -
    -
    -
    -
    -
    - -

    Select applications...

    - -
    -
    - -
    -
    -
  • -
-
- -
- -
-
- -

- - -
Failed to communicate with the - widget microservice.
- -
-
    -
  • -
    -
    - -

    {{ widget.headerText}}

    -
    - ... - - - -
    -
    -
    -
    -
    -
    -
  • -
-
-
-
-
- Add Widget -
-   -
- Reset Widget Layout -
-
-
- -
-
diff --git a/ecomp-portal-FE-os/client/src/views/footer/footer.controller.js b/ecomp-portal-FE-os/client/src/views/footer/footer.controller.js index 34d3d960..5db3ed0f 100644 --- a/ecomp-portal-FE-os/client/src/views/footer/footer.controller.js +++ b/ecomp-portal-FE-os/client/src/views/footer/footer.controller.js @@ -1,48 +1,48 @@ -/*- - * ================================================================================ - * 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 FooterCtrl { - constructor($scope, $rootScope, manifestService, $log) { - this.manifestService = manifestService; - this.$log = $log; - this.$scope = $scope; - this.$rootScope = $rootScope; - - $scope.buildinfo = null; - - $rootScope.showFooter = true; - $scope.date = new Date(); - - - manifestService.getManifest().then( jsonObj => { - // $log.debug('FooterCtrl.getManifest: ', JSON.stringify(jsonObj)); - $scope.buildInfo = jsonObj; - - }).catch(err=> { - $log.error('FooterCtrl::updateTableData error :',err); - }); - }; - - } - - FooterCtrl.$inject = ['$scope', '$rootScope', 'manifestService', '$log']; - angular.module('ecompApp').controller('FooterCtrl', FooterCtrl); -})(); +/*- + * ================================================================================ + * 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 FooterCtrl { + constructor($scope, $rootScope, manifestService, $log) { + this.manifestService = manifestService; + this.$log = $log; + this.$scope = $scope; + this.$rootScope = $rootScope; + + $scope.buildinfo = null; + + $rootScope.showFooter = true; + $scope.date = new Date(); + + + manifestService.getManifest().then( jsonObj => { + // $log.debug('FooterCtrl.getManifest: ', JSON.stringify(jsonObj)); + $scope.buildInfo = jsonObj; + + }).catch(err=> { + $log.error('FooterCtrl::updateTableData error :',err); + }); + }; + + } + + FooterCtrl.$inject = ['$scope', '$rootScope', 'manifestService', '$log']; + angular.module('ecompApp').controller('FooterCtrl', FooterCtrl); +})(); diff --git a/ecomp-portal-FE-os/client/src/views/footer/footer.controller.spec.js b/ecomp-portal-FE-os/client/src/views/footer/footer.controller.spec.js index 3841a2b3..32cc3a1f 100644 --- a/ecomp-portal-FE-os/client/src/views/footer/footer.controller.spec.js +++ b/ecomp-portal-FE-os/client/src/views/footer/footer.controller.spec.js @@ -1,19 +1,19 @@ -/*- - * ================================================================================ - * 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. - * ================================================================================ - */ +/*- + * ================================================================================ + * 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. + * ================================================================================ + */ diff --git a/ecomp-portal-FE-os/client/src/views/footer/footer.less b/ecomp-portal-FE-os/client/src/views/footer/footer.less index 59c8622e..0004b02b 100644 --- a/ecomp-portal-FE-os/client/src/views/footer/footer.less +++ b/ecomp-portal-FE-os/client/src/views/footer/footer.less @@ -1,104 +1,104 @@ -.w-ecomp-footer { - z-index: 101; - background-color: #222; - position: absolute; - bottom: 0; - width: 100%; - height: @footer-height; - .white12r; - - a { - .white12r; - font-family: Arial; - font-size: 11px; - } - - .footer-image { - margin: auto; - - } - - .build-number { - float: right; - padding: 5px; - } - .footer-content { - align-items: center; - text-align: center; - vertical-align: middle; - display: flex; - justify-content: center; - //width: @table-width; - margin: auto; - - } - - [class*="icon-primary-"], .cssIcon-globe:before { - color: #0574ac; - display: inline-block; - font-family: 'icoPrimary' !important; - font-style: normal; - font-size: 20px; - font-weight: normal; - font-variant: normal; - height: 1em; - margin-right: 7px; - text-transform: none; - line-height: 1; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - position: relative; - speak: none; - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; - vertical-align: middle; - width: 1em; - } - - .footer-logo { - color: #000 !important; - } - .footerWrapper .footer-logo .logo-title { - color: #fff; - margin-left: 10px; - display: inline-block; - font-size: 25px; - margin-top: 0px; - font-family: Arial; - font-weight: normal; - } - .displayInline { - display: inline-block; - margin-left: 20px; - margin-top: 20px; - } - .footerWrapper .copyright-text { - color: #fff; - font-size: 11px; - font-family: Arial; - margin-bottom:0px; - margin-top: 15px; - line-height: 1rem; - margin-top: 20px; - margin-left: 100px; - } - .footerText { - width: 59%; - float: left; - text-align: left; - margin-left: 50px; - } - .footerLastSection { - width: 1200px; - margin: auto; - } - .build-number{ - margin-top:-14px; - margin-right: -195px; - } - .footer-link{ - text-decoration: underline; - } -} +.w-ecomp-footer { + z-index: 101; + background-color: #222; + position: absolute; + bottom: 0; + width: 100%; + height: @footer-height; + .white12r; + + a { + .white12r; + font-family: Arial; + font-size: 11px; + } + + .footer-image { + margin: auto; + + } + + .build-number { + float: right; + padding: 5px; + } + .footer-content { + align-items: center; + text-align: center; + vertical-align: middle; + display: flex; + justify-content: center; + //width: @table-width; + margin: auto; + + } + + [class*="icon-primary-"], .cssIcon-globe:before { + color: #0574ac; + display: inline-block; + font-family: 'icoPrimary' !important; + font-style: normal; + font-size: 20px; + font-weight: normal; + font-variant: normal; + height: 1em; + margin-right: 7px; + text-transform: none; + line-height: 1; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + position: relative; + speak: none; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + vertical-align: middle; + width: 1em; + } + + .footer-logo { + color: #000 !important; + } + .footerWrapper .footer-logo .logo-title { + color: #fff; + margin-left: 10px; + display: inline-block; + font-size: 25px; + margin-top: 0px; + font-family: Arial; + font-weight: normal; + } + .displayInline { + display: inline-block; + margin-left: 20px; + margin-top: 20px; + } + .footerWrapper .copyright-text { + color: #fff; + font-size: 11px; + font-family: Arial; + margin-bottom:0px; + margin-top: 15px; + line-height: 1rem; + margin-top: 20px; + margin-left: 100px; + } + .footerText { + width: 59%; + float: left; + text-align: left; + margin-left: 50px; + } + .footerLastSection { + width: 1200px; + margin: auto; + } + .build-number{ + margin-top:-14px; + margin-right: -195px; + } + .footer-link{ + text-decoration: underline; + } +} diff --git a/ecomp-portal-FE-os/client/src/views/footer/footer.tpl.html b/ecomp-portal-FE-os/client/src/views/footer/footer.tpl.html index a6fbdeea..37148abf 100644 --- a/ecomp-portal-FE-os/client/src/views/footer/footer.tpl.html +++ b/ecomp-portal-FE-os/client/src/views/footer/footer.tpl.html @@ -1,34 +1,34 @@ - - + + diff --git a/ecomp-portal-FE-os/client/src/views/functionalMenu/functionalMenu-dialog/menu-details.controller.js b/ecomp-portal-FE-os/client/src/views/functionalMenu/functionalMenu-dialog/menu-details.controller.js index 09a8e75a..140aea94 100644 --- a/ecomp-portal-FE-os/client/src/views/functionalMenu/functionalMenu-dialog/menu-details.controller.js +++ b/ecomp-portal-FE-os/client/src/views/functionalMenu/functionalMenu-dialog/menu-details.controller.js @@ -1,415 +1,415 @@ -/*- - * ================================================================================ - * 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 MenuDetailsModalCtrl { - constructor($scope, $log, functionalMenuService, errorMessageByCode, ECOMP_URL_REGEX,$rootScope,confirmBoxService) { - - - let newMenuModel = { - name: null, - menuId: null, - parentMenuId: null, - url: null - }; - - let getAvailableRoles = (appid) => { - this.isSaving = true; - if (appid != null) { - $log.debug("MenuDetailsModalCtrl::getAvailableRoles: About to call getManagedRolesMenu"); - functionalMenuService.getManagedRolesMenu(appid).then(rolesObj => { - $log.debug("MenuDetailsModalCtrl::getAvailableRoles: Roles returned = " + JSON.stringify(rolesObj)) - this.availableRoles = rolesObj; - this.preSelectedRoles = {roles:[]}; - - if(($scope.ngDialogData.source==='edit') && this.isMidLevelMenuItem()){ - // in Edit flow , for Midlevel menu item no need to preSelect. - this.preSelectedRoles = {roles:[]}; - }else if(!angular.isUndefined(this.menuItem.menuDetails) && - $scope.ngDialogData.source==='edit' && this.isLeafMenuItem() && - this.menuItem.menuDetails.appid!=appid) { - // in Edit flow , for LeafMenuItem, if appid changed then no need to preSelect. - this.preSelectedRoles = {roles:[]}; - }else{ - if((!angular.isUndefined(this.menuItem.menuDetails)) && - (!angular.isUndefined(this.menuItem.menuDetails.roles))){ - $log.debug('menuDetails.roles: ' + this.menuItem.menuDetails.roles); - for(var i=0; i { - $log.error("MenuDetailsModalCtrl::getAvailableRoles: error: " + err); - }); - } else { - $log.debug("MenuDetailsModalCtrl::getAvailableRoles: appid was null"); - } - }; - - let getAvailableApps = () => { - functionalMenuService.getAvailableApplications().then(apps => { - $log.debug("MenuDetailsModalCtrl::getAvailableApps: Apps returned = " + JSON.stringify(apps)) - this.availableApps = apps; - // Keep track of whether or not the selected app is disabled - if (angular.isDefined(this.selectedApp) && angular.isDefined(this.selectedApp.index)) { - for (var i = 0; i < apps.length; i++) { - if (apps[i].index === this.selectedApp.index) { - $log.debug("MenuDetailsModalCtrl::getAvailableApps: found app with index: " + this.selectedApp.index); - $log.debug("MenuDetailsModalCtrl::getAvailableApps: setting isDisabled to: " + !apps[i].enabled); - this.selectedApp.isDisabled = !apps[i].enabled; - break; - } - } - $log.debug("didn't find index: " + this.selectedApp.index); - } - })['catch'](function (err) { - confirmBoxService.showInformation('There was a problem retrieving the Applications. ' + - 'Please try again later. Error Status: '+ err.status).then(isConfirmed => {}); - $log.error("MenuDetailsModalCtrl::getAvailableApps: getAvailableApps error: " + err); - }).finally(()=>{ - this.isSaving = false; - }); - }; - - let init = () => { - $log.info('MenuDetailsModalCtrl::init'); - this.saveOrContinueBtnText = "Save"; - this.isSaving = false; - this.displayRoles = $scope.ngDialogData.source==='view' ? true : false; - this.formEditable = $scope.ngDialogData.source==='view' ? false : true; - this.selectedRole = []; - this.availableRoles = []; - this.menuItem = _.clone($scope.ngDialogData.menuItem); - $log.info('MenuDetailsModalCtrl::getAvailableApps: Within init, about to check menuDetails for defined'); - if(!angular.isUndefined(this.menuItem.menuDetails) && - ($scope.ngDialogData.source==='view' || - ($scope.ngDialogData.source==='edit') && this.isLeafMenuItem() )){ - - $log.debug("MenuDetailsModalCtrl::init: menuItem: "); - $log.debug('MenuDetailsModalCtrl::init: ',this.menuItem); - this.menuItem.menu.url = this.menuItem.menuDetails.url; - this.selectedApp={}; - this.selectedApp.index = this.menuItem.menuDetails.appid; - getAvailableRoles(this.selectedApp.index); - - } - - if($scope.ngDialogData.source==='view' || $scope.ngDialogData.source==='edit'){ - this.menutitle = this.menuItem.menu.name; - this.menuLocation = this.isParentMenuItem() ? this.menuItem.menu.name : this.menuItem.menu.parent.name; - }else{ - this.menutitle = ''; - this.menuLocation = this.menuItem.menu.name; - } - // Temporarily passing 0 as dummy for getAvailableRoles incase of this.selectedApp is not there i.e., in Add flow - // getAvailableRoles(angular.isUndefined(this.selectedApp) ? 0: this.selectedApp.index ); - getAvailableApps(); - $log.debug("MenuDetailsModalCtrl::init: Menu details: " + JSON.stringify(this.menuItem.menuDetails)); - }; - - - this.ECOMP_URL_REGEX = ECOMP_URL_REGEX; - - //This part handles conflict errors (409) - this.conflictMessages = {}; - this.scrollApi = {}; - let handleConflictErrors = err => { - if(!err.data){ - return; - } - if(!err.data.length){ //support objects - err.data = [err.data] - } - $log.debug('MenuDetailsModalCtrl::handleConflictErrors: err.data = ' + JSON.stringify(err.data)); - _.forEach(err.data, item => { - _.forEach(item.fields, field => { - //set conflict message - this.conflictMessages[field.name] = errorMessageByCode[item.errorCode]; - //set field as invalid - $log.debug('MenuDetailsModalCtrl::handleConflictErrors: fieldName = ' + field.name); - $scope.functionalMenuForm[field.name].$setValidity('conflict', false); - //set watch once to clear error after user correction - watchOnce[field.name](); - }); - }); - this.scrollApi.scrollTop(); - }; - - let resetConflict = fieldName => { - delete this.conflictMessages[fieldName]; - $log.debug('MenuDetailsModalCtrl::resetConflict: $setValidity(true) = ' + fieldName); - if($scope.functionalMenuForm[fieldName]){ - $scope.functionalMenuForm[fieldName].$setValidity('conflict', true); - } - }; - - let watchOnce = { - text: () => { - let unregisterName = $scope.$watch('functionalMenuDetails.menutitle', (newVal, oldVal) => { - // $log.debug('title:: newVal, oldVal = ' + newVal.toLowerCase() + " | " + oldVal.toLowerCase()); - if(newVal.toLowerCase() !== oldVal.toLowerCase()){ - resetConflict('text'); - unregisterName(); - } - }); - }, - url: () => { - let unregisterUrl = $scope.$watch('functionalMenuDetails.menuItem.menu.url', (newVal, oldVal) => { - if(newVal.toLowerCase() !== oldVal.toLowerCase()){ - resetConflict('url'); - unregisterUrl(); - } - }); - } - }; - - //*************************** - - this.isLeafMenuItem = () => { - return this.menuItem.menu.children.length>0 ? false : true; - }; - - this.isMidLevelMenuItem = () => { - return this.menuItem.menu.parentMenuId!=null && this.menuItem.menu.children.length>0 ? true : false; - }; - - this.isParentMenuItem = () => { - return this.menuItem.menu.parentMenuId!=null ? false : true; - }; - - this.updateSelectedApp = (appItem) => { - if (!appItem) { - return; - } - $log.debug('MenuDetailsModalCtrl::updateSelectedApp: drop down app item = ' + JSON.stringify(appItem.index)); - $log.debug("MenuDetailsModalCtrl::updateSelectedApp: appItem in updateSelectedApp: "); - $log.debug('MenuDetailsModalCtrl::updateSelectedApp: ',appItem); - this.selectedApp.isDisabled = ! appItem.enabled; - $log.debug("MenuDetailsModalCtrl::updateSelectedApp: isDisabled: "+this.selectedApp.isDisabled); - getAvailableRoles(appItem.index); - }; - - this.continue = () => { - this.displayRoles = true; - this.formEditable = false; - }; - - this.saveChanges = () => { - - //todo : form validation was commented as dialog message is kept for error validations - /*if($scope.functionalMenuForm.$invalid){ - return; - }*/ - - if(!!this.menuItem.menu.url && (angular.isUndefined(this.selectedApp) || !this.selectedApp.index>0)) { - confirmBoxService.showInformation('Please select the appropriate app, or remove the url').then(isConfirmed => {}); - return; - }else if(!this.menuItem.menu.url && !angular.isUndefined(this.selectedApp) && this.selectedApp.index>0){ - confirmBoxService.showInformation('Please enter url, or select "No Application"').then(isConfirmed => {}); - return; - }else if(!this.menutitle){ - confirmBoxService.showInformation('Please enter the Menu title').then(isConfirmed => {}); - return; - } - - this.isSaving = true; - var activeMenuItem = {}; - - if ($scope.ngDialogData.source === 'edit') { // Edit Menu Item - $log.debug('MenuDetailsModalCtrl::saveChanges: Will be saving an edit menu item'); - activeMenuItem = { - menuId:this.menuItem.menu.menuId, - column:this.menuItem.menu.column, - text:this.menutitle, - parentMenuId:this.menuItem.menu.parentMenuId, - url:this.menuItem.menu.url, - appid: angular.isUndefined(this.selectedApp) ? null:this.selectedApp.index, - roles:this.selectedRole - }; - // If we have removed the url and appid, we must remove the roles - if (!activeMenuItem.appid && !activeMenuItem.url) { - activeMenuItem.roles = null; - } - functionalMenuService.saveEditedMenuItem(activeMenuItem) - .then(() => { - $log.debug('MenuDetailsModalCtrl::saveChanges: Menu Item saved'); - $scope.closeThisDialog(true); - }).catch(err => { - if(err.status === 409){//Conflict - handleConflictErrors(err); - } else { - confirmBoxService.showInformation('There was a problem saving your change. ' + - 'Please try again later. Error Status: '+ err.status).then(isConfirmed => {}); - } - $log.error('MenuDetailsModalCtrl::saveChanges: error - ',err); - }).finally(()=>{ - this.isSaving = false; - }); - - $log.debug("MenuDetailsModalCtrl::saveChanges: Edit Menu output will be: " + JSON.stringify(activeMenuItem)); - } else { // New Menu Item - $log.debug('MenuDetailsModalCtrl::saveChanges: Will be saving a New menu item'); - var newMenuItem = { - menuId:null, // this is a new menu item - column:this.menuItem.menu.column, - text:this.menutitle, - // We are creating this new menu item under the menu item that was clicked on. - parentMenuId:this.menuItem.menu.menuId, - url:this.menuItem.menu.url, - appid: angular.isUndefined(this.selectedApp) ? null:this.selectedApp.index, - roles:this.selectedRole - }; - - $log.debug("MenuDetailsModalCtrl::saveChanges: New Menu output will be: " + JSON.stringify(newMenuItem)); - functionalMenuService.saveMenuItem(newMenuItem) - .then(() => { - $log.debug('MenuDetailsModalCtrl::saveChanges: Menu Item saved'); - $scope.closeThisDialog(true); - }).catch(err => { - if(err.status === 409){//Conflict - handleConflictErrors(err); - } else { - confirmBoxService.showInformation('There was a problem saving your menu. ' + - 'Please try again later. Error Status: '+ err.status).then(isConfirmed => {}); - } - $log.error('MenuDetailsModalCtrl::saveChanges error: ', err); - }).finally(()=>{ - this.isSaving = false; - }); - - } - }; - - init(); - - $scope.$on('$stateChangeStart', e => { - //Disable navigation when modal is opened - e.preventDefault(); - }); - } - } - MenuDetailsModalCtrl.$inject = ['$scope', '$log', 'functionalMenuService', 'errorMessageByCode', 'ECOMP_URL_REGEX','$rootScope','confirmBoxService']; - angular.module('ecompApp').controller('MenuDetailsModalCtrl', MenuDetailsModalCtrl); - - angular.module('ecompApp').directive('dropdownMultiselect', ['functionalMenuService',function(){ - return { - restrict: 'E', - scope: { - model: '=', - options: '=', - populated_roles: '=preSelected', - dropdownTitle: '@', - source: '=' - }, - template: "
" + - "" + - "" + - "" + - "
", - controller: function ($scope) { - $scope.selectedItems = {}; - $scope.checkAll = false; - $scope.$on('availableRolesReady', function() { - init(); - }); - - function init() { - console.log('dropdownMultiselect init'); - $scope.dropdownTitle = $scope.source ==='view' ? 'View Roles' : 'Select Roles'; - console.log('$scope.populated_roles = ' + $scope.populated_roles); - } - - $scope.$watch('populated_roles', function(){ - if ($scope.populated_roles && $scope.populated_roles.length>0) { - for (var i = 0; i < $scope.populated_roles.length; i++) { - $scope.model.push($scope.populated_roles[i].roleId); - $scope.selectedItems[$scope.populated_roles[i].roleId] = true; - } - if ($scope.populated_roles.length === $scope.options.length) { - $scope.checkAll = true; - } - }else{ - deselectAll(); - } - }); - - $scope.openDropDown = function () { - - }; - - $scope.checkAllClicked = function () { - if ($scope.checkAll) { - selectAll(); - } else { - deselectAll(); - } - }; - - function selectAll() { - $scope.model = []; - $scope.selectedItems = {}; - angular.forEach($scope.options, function (option) { - $scope.model.push(option.roleId); - }); - angular.forEach($scope.model, function (id) { - $scope.selectedItems[id] = true; - }); - console.log($scope.model); - }; - - function deselectAll() { - $scope.model = []; - $scope.selectedItems = {}; - console.log($scope.model); - }; - - $scope.setSelectedItem = function (id) { - var filteredArray = []; - if ($scope.selectedItems[id] === true) { - $scope.model.push(id); - } else { - filteredArray = $scope.model.filter(function (value) { - return value != id; - }); - $scope.model = filteredArray; - $scope.checkAll = false; - } - console.log(filteredArray); - return false; - }; - - $scope.setDisable = function(source){ - return source ==='view' ? true : false; - } - } - } - }]); - -})(); +/*- + * ================================================================================ + * 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 MenuDetailsModalCtrl { + constructor($scope, $log, functionalMenuService, errorMessageByCode, ECOMP_URL_REGEX,$rootScope,confirmBoxService) { + + + let newMenuModel = { + name: null, + menuId: null, + parentMenuId: null, + url: null + }; + + let getAvailableRoles = (appid) => { + this.isSaving = true; + if (appid != null) { + $log.debug("MenuDetailsModalCtrl::getAvailableRoles: About to call getManagedRolesMenu"); + functionalMenuService.getManagedRolesMenu(appid).then(rolesObj => { + $log.debug("MenuDetailsModalCtrl::getAvailableRoles: Roles returned = " + JSON.stringify(rolesObj)) + this.availableRoles = rolesObj; + this.preSelectedRoles = {roles:[]}; + + if(($scope.ngDialogData.source==='edit') && this.isMidLevelMenuItem()){ + // in Edit flow , for Midlevel menu item no need to preSelect. + this.preSelectedRoles = {roles:[]}; + }else if(!angular.isUndefined(this.menuItem.menuDetails) && + $scope.ngDialogData.source==='edit' && this.isLeafMenuItem() && + this.menuItem.menuDetails.appid!=appid) { + // in Edit flow , for LeafMenuItem, if appid changed then no need to preSelect. + this.preSelectedRoles = {roles:[]}; + }else{ + if((!angular.isUndefined(this.menuItem.menuDetails)) && + (!angular.isUndefined(this.menuItem.menuDetails.roles))){ + $log.debug('menuDetails.roles: ' + this.menuItem.menuDetails.roles); + for(var i=0; i { + $log.error("MenuDetailsModalCtrl::getAvailableRoles: error: " + err); + }); + } else { + $log.debug("MenuDetailsModalCtrl::getAvailableRoles: appid was null"); + } + }; + + let getAvailableApps = () => { + functionalMenuService.getAvailableApplications().then(apps => { + $log.debug("MenuDetailsModalCtrl::getAvailableApps: Apps returned = " + JSON.stringify(apps)) + this.availableApps = apps; + // Keep track of whether or not the selected app is disabled + if (angular.isDefined(this.selectedApp) && angular.isDefined(this.selectedApp.index)) { + for (var i = 0; i < apps.length; i++) { + if (apps[i].index === this.selectedApp.index) { + $log.debug("MenuDetailsModalCtrl::getAvailableApps: found app with index: " + this.selectedApp.index); + $log.debug("MenuDetailsModalCtrl::getAvailableApps: setting isDisabled to: " + !apps[i].enabled); + this.selectedApp.isDisabled = !apps[i].enabled; + break; + } + } + $log.debug("didn't find index: " + this.selectedApp.index); + } + })['catch'](function (err) { + confirmBoxService.showInformation('There was a problem retrieving the Applications. ' + + 'Please try again later. Error Status: '+ err.status).then(isConfirmed => {}); + $log.error("MenuDetailsModalCtrl::getAvailableApps: getAvailableApps error: " + err); + }).finally(()=>{ + this.isSaving = false; + }); + }; + + let init = () => { + $log.info('MenuDetailsModalCtrl::init'); + this.saveOrContinueBtnText = "Save"; + this.isSaving = false; + this.displayRoles = $scope.ngDialogData.source==='view' ? true : false; + this.formEditable = $scope.ngDialogData.source==='view' ? false : true; + this.selectedRole = []; + this.availableRoles = []; + this.menuItem = _.clone($scope.ngDialogData.menuItem); + $log.info('MenuDetailsModalCtrl::getAvailableApps: Within init, about to check menuDetails for defined'); + if(!angular.isUndefined(this.menuItem.menuDetails) && + ($scope.ngDialogData.source==='view' || + ($scope.ngDialogData.source==='edit') && this.isLeafMenuItem() )){ + + $log.debug("MenuDetailsModalCtrl::init: menuItem: "); + $log.debug('MenuDetailsModalCtrl::init: ',this.menuItem); + this.menuItem.menu.url = this.menuItem.menuDetails.url; + this.selectedApp={}; + this.selectedApp.index = this.menuItem.menuDetails.appid; + getAvailableRoles(this.selectedApp.index); + + } + + if($scope.ngDialogData.source==='view' || $scope.ngDialogData.source==='edit'){ + this.menutitle = this.menuItem.menu.name; + this.menuLocation = this.isParentMenuItem() ? this.menuItem.menu.name : this.menuItem.menu.parent.name; + }else{ + this.menutitle = ''; + this.menuLocation = this.menuItem.menu.name; + } + // Temporarily passing 0 as dummy for getAvailableRoles incase of this.selectedApp is not there i.e., in Add flow + // getAvailableRoles(angular.isUndefined(this.selectedApp) ? 0: this.selectedApp.index ); + getAvailableApps(); + $log.debug("MenuDetailsModalCtrl::init: Menu details: " + JSON.stringify(this.menuItem.menuDetails)); + }; + + + this.ECOMP_URL_REGEX = ECOMP_URL_REGEX; + + //This part handles conflict errors (409) + this.conflictMessages = {}; + this.scrollApi = {}; + let handleConflictErrors = err => { + if(!err.data){ + return; + } + if(!err.data.length){ //support objects + err.data = [err.data] + } + $log.debug('MenuDetailsModalCtrl::handleConflictErrors: err.data = ' + JSON.stringify(err.data)); + _.forEach(err.data, item => { + _.forEach(item.fields, field => { + //set conflict message + this.conflictMessages[field.name] = errorMessageByCode[item.errorCode]; + //set field as invalid + $log.debug('MenuDetailsModalCtrl::handleConflictErrors: fieldName = ' + field.name); + $scope.functionalMenuForm[field.name].$setValidity('conflict', false); + //set watch once to clear error after user correction + watchOnce[field.name](); + }); + }); + this.scrollApi.scrollTop(); + }; + + let resetConflict = fieldName => { + delete this.conflictMessages[fieldName]; + $log.debug('MenuDetailsModalCtrl::resetConflict: $setValidity(true) = ' + fieldName); + if($scope.functionalMenuForm[fieldName]){ + $scope.functionalMenuForm[fieldName].$setValidity('conflict', true); + } + }; + + let watchOnce = { + text: () => { + let unregisterName = $scope.$watch('functionalMenuDetails.menutitle', (newVal, oldVal) => { + // $log.debug('title:: newVal, oldVal = ' + newVal.toLowerCase() + " | " + oldVal.toLowerCase()); + if(newVal.toLowerCase() !== oldVal.toLowerCase()){ + resetConflict('text'); + unregisterName(); + } + }); + }, + url: () => { + let unregisterUrl = $scope.$watch('functionalMenuDetails.menuItem.menu.url', (newVal, oldVal) => { + if(newVal.toLowerCase() !== oldVal.toLowerCase()){ + resetConflict('url'); + unregisterUrl(); + } + }); + } + }; + + //*************************** + + this.isLeafMenuItem = () => { + return this.menuItem.menu.children.length>0 ? false : true; + }; + + this.isMidLevelMenuItem = () => { + return this.menuItem.menu.parentMenuId!=null && this.menuItem.menu.children.length>0 ? true : false; + }; + + this.isParentMenuItem = () => { + return this.menuItem.menu.parentMenuId!=null ? false : true; + }; + + this.updateSelectedApp = (appItem) => { + if (!appItem) { + return; + } + $log.debug('MenuDetailsModalCtrl::updateSelectedApp: drop down app item = ' + JSON.stringify(appItem.index)); + $log.debug("MenuDetailsModalCtrl::updateSelectedApp: appItem in updateSelectedApp: "); + $log.debug('MenuDetailsModalCtrl::updateSelectedApp: ',appItem); + this.selectedApp.isDisabled = ! appItem.enabled; + $log.debug("MenuDetailsModalCtrl::updateSelectedApp: isDisabled: "+this.selectedApp.isDisabled); + getAvailableRoles(appItem.index); + }; + + this.continue = () => { + this.displayRoles = true; + this.formEditable = false; + }; + + this.saveChanges = () => { + + //todo : form validation was commented as dialog message is kept for error validations + /*if($scope.functionalMenuForm.$invalid){ + return; + }*/ + + if(!!this.menuItem.menu.url && (angular.isUndefined(this.selectedApp) || !this.selectedApp.index>0)) { + confirmBoxService.showInformation('Please select the appropriate app, or remove the url').then(isConfirmed => {}); + return; + }else if(!this.menuItem.menu.url && !angular.isUndefined(this.selectedApp) && this.selectedApp.index>0){ + confirmBoxService.showInformation('Please enter url, or select "No Application"').then(isConfirmed => {}); + return; + }else if(!this.menutitle){ + confirmBoxService.showInformation('Please enter the Menu title').then(isConfirmed => {}); + return; + } + + this.isSaving = true; + var activeMenuItem = {}; + + if ($scope.ngDialogData.source === 'edit') { // Edit Menu Item + $log.debug('MenuDetailsModalCtrl::saveChanges: Will be saving an edit menu item'); + activeMenuItem = { + menuId:this.menuItem.menu.menuId, + column:this.menuItem.menu.column, + text:this.menutitle, + parentMenuId:this.menuItem.menu.parentMenuId, + url:this.menuItem.menu.url, + appid: angular.isUndefined(this.selectedApp) ? null:this.selectedApp.index, + roles:this.selectedRole + }; + // If we have removed the url and appid, we must remove the roles + if (!activeMenuItem.appid && !activeMenuItem.url) { + activeMenuItem.roles = null; + } + functionalMenuService.saveEditedMenuItem(activeMenuItem) + .then(() => { + $log.debug('MenuDetailsModalCtrl::saveChanges: Menu Item saved'); + $scope.closeThisDialog(true); + }).catch(err => { + if(err.status === 409){//Conflict + handleConflictErrors(err); + } else { + confirmBoxService.showInformation('There was a problem saving your change. ' + + 'Please try again later. Error Status: '+ err.status).then(isConfirmed => {}); + } + $log.error('MenuDetailsModalCtrl::saveChanges: error - ',err); + }).finally(()=>{ + this.isSaving = false; + }); + + $log.debug("MenuDetailsModalCtrl::saveChanges: Edit Menu output will be: " + JSON.stringify(activeMenuItem)); + } else { // New Menu Item + $log.debug('MenuDetailsModalCtrl::saveChanges: Will be saving a New menu item'); + var newMenuItem = { + menuId:null, // this is a new menu item + column:this.menuItem.menu.column, + text:this.menutitle, + // We are creating this new menu item under the menu item that was clicked on. + parentMenuId:this.menuItem.menu.menuId, + url:this.menuItem.menu.url, + appid: angular.isUndefined(this.selectedApp) ? null:this.selectedApp.index, + roles:this.selectedRole + }; + + $log.debug("MenuDetailsModalCtrl::saveChanges: New Menu output will be: " + JSON.stringify(newMenuItem)); + functionalMenuService.saveMenuItem(newMenuItem) + .then(() => { + $log.debug('MenuDetailsModalCtrl::saveChanges: Menu Item saved'); + $scope.closeThisDialog(true); + }).catch(err => { + if(err.status === 409){//Conflict + handleConflictErrors(err); + } else { + confirmBoxService.showInformation('There was a problem saving your menu. ' + + 'Please try again later. Error Status: '+ err.status).then(isConfirmed => {}); + } + $log.error('MenuDetailsModalCtrl::saveChanges error: ', err); + }).finally(()=>{ + this.isSaving = false; + }); + + } + }; + + init(); + + $scope.$on('$stateChangeStart', e => { + //Disable navigation when modal is opened + e.preventDefault(); + }); + } + } + MenuDetailsModalCtrl.$inject = ['$scope', '$log', 'functionalMenuService', 'errorMessageByCode', 'ECOMP_URL_REGEX','$rootScope','confirmBoxService']; + angular.module('ecompApp').controller('MenuDetailsModalCtrl', MenuDetailsModalCtrl); + + angular.module('ecompApp').directive('dropdownMultiselect', ['functionalMenuService',function(){ + return { + restrict: 'E', + scope: { + model: '=', + options: '=', + populated_roles: '=preSelected', + dropdownTitle: '@', + source: '=' + }, + template: "
" + + "" + + "" + + "" + + "
", + controller: function ($scope) { + $scope.selectedItems = {}; + $scope.checkAll = false; + $scope.$on('availableRolesReady', function() { + init(); + }); + + function init() { + console.log('dropdownMultiselect init'); + $scope.dropdownTitle = $scope.source ==='view' ? 'View Roles' : 'Select Roles'; + console.log('$scope.populated_roles = ' + $scope.populated_roles); + } + + $scope.$watch('populated_roles', function(){ + if ($scope.populated_roles && $scope.populated_roles.length>0) { + for (var i = 0; i < $scope.populated_roles.length; i++) { + $scope.model.push($scope.populated_roles[i].roleId); + $scope.selectedItems[$scope.populated_roles[i].roleId] = true; + } + if ($scope.populated_roles.length === $scope.options.length) { + $scope.checkAll = true; + } + }else{ + deselectAll(); + } + }); + + $scope.openDropDown = function () { + + }; + + $scope.checkAllClicked = function () { + if ($scope.checkAll) { + selectAll(); + } else { + deselectAll(); + } + }; + + function selectAll() { + $scope.model = []; + $scope.selectedItems = {}; + angular.forEach($scope.options, function (option) { + $scope.model.push(option.roleId); + }); + angular.forEach($scope.model, function (id) { + $scope.selectedItems[id] = true; + }); + console.log($scope.model); + }; + + function deselectAll() { + $scope.model = []; + $scope.selectedItems = {}; + console.log($scope.model); + }; + + $scope.setSelectedItem = function (id) { + var filteredArray = []; + if ($scope.selectedItems[id] === true) { + $scope.model.push(id); + } else { + filteredArray = $scope.model.filter(function (value) { + return value != id; + }); + $scope.model = filteredArray; + $scope.checkAll = false; + } + console.log(filteredArray); + return false; + }; + + $scope.setDisable = function(source){ + return source ==='view' ? true : false; + } + } + } + }]); + +})(); diff --git a/ecomp-portal-FE-os/client/src/views/functionalMenu/functionalMenu-dialog/menu-details.delete.modal.html b/ecomp-portal-FE-os/client/src/views/functionalMenu/functionalMenu-dialog/menu-details.delete.modal.html index f5f027c3..674affa2 100644 --- a/ecomp-portal-FE-os/client/src/views/functionalMenu/functionalMenu-dialog/menu-details.delete.modal.html +++ b/ecomp-portal-FE-os/client/src/views/functionalMenu/functionalMenu-dialog/menu-details.delete.modal.html @@ -1,37 +1,37 @@ - -
-
Delete Menu Item
- -
-
- -
-
-
- -
-
- - - -
-
+ +
+
Delete Menu Item
+ +
+
+ +
+
+
+ +
+
+ + + +
+
diff --git a/ecomp-portal-FE-os/client/src/views/functionalMenu/functionalMenu-dialog/menu-details.modal.html b/ecomp-portal-FE-os/client/src/views/functionalMenu/functionalMenu-dialog/menu-details.modal.html index aebc6a52..56c3f4dc 100644 --- a/ecomp-portal-FE-os/client/src/views/functionalMenu/functionalMenu-dialog/menu-details.modal.html +++ b/ecomp-portal-FE-os/client/src/views/functionalMenu/functionalMenu-dialog/menu-details.modal.html @@ -1,103 +1,103 @@ - -
-
{{ngDialogData.title}}
- - -
-
- -
-
Parent
- -
-
-
Title
- -
- -
-
-
-
-
URL
- - Not valid URL! -
-
-
App
-
- -
- - -
-
-
-
Roles
- - -
-
Application is disabled
- -
-
-
- - - - - - - - - - -
-
-
Close
-
-
-
+ +
+
{{ngDialogData.title}}
+ + +
+
+ +
+
Parent
+ +
+
+
Title
+ +
+ +
+
+
+
+
URL
+ + Not valid URL! +
+
+
App
+
+ +
+ + +
+
+
+
Roles
+ + +
+
Application is disabled
+ +
+
+
+ + + + + + + + + + +
+
+
Close
+
+
+
diff --git a/ecomp-portal-FE-os/client/src/views/functionalMenu/functionalMenu.controller.js b/ecomp-portal-FE-os/client/src/views/functionalMenu/functionalMenu.controller.js index dedc1375..343c968d 100644 --- a/ecomp-portal-FE-os/client/src/views/functionalMenu/functionalMenu.controller.js +++ b/ecomp-portal-FE-os/client/src/views/functionalMenu/functionalMenu.controller.js @@ -1,372 +1,372 @@ -/*- - * ================================================================================ - * 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 FunctionalMenuCtrl { - constructor($log, functionalMenuService, $scope,ngDialog, confirmBoxService) { - $log.info('FunctionalMenuCtrl init'); - - $scope.invokeDialog = () => { - // alert("click dialog"); - }; - - this.regenerateFunctionalMenuAncestors = () => { - functionalMenuService.regenerateFunctionalMenuAncestors().then(res => { - $log.debug("FunctionalMenuCtrl:regenerateFunctionalMenuAncestors::returned from regenerateFunctionalMenuAncestors API call"); - confirmBoxService.showInformation('You have successfully regenerated the menu.').then(isConfirmed => { - }); - })['catch'](function (err) { - $log.error("FunctionalMenuCtrl:regenerateFunctionalMenuAncestors:: error: " + err); - confirmBoxService.showInformation('There was an error while regenerating the menu.').then(isConfirmed => { - }); - }); - }; - - let getFunctionalMenu = () => { - this.isLoadingTable = true; - functionalMenuService.getManagedFunctionalMenu().then(res => { - - let actualData=[]; - - //Adding children and label attribute to all objects in res - for(let i = 0; i < res.length; i++){ - res[i].children=[]; - res[i].label=res[i].text; - res[i].id=res[i].text; - - } - //Adding actual child items to children array in res objects - for(let i = 0; i < res.length; i++){ - - let parentId=res[i].menuId; - for(let j = 0; j < res.length; j++){ - let childId=res[j].parentMenuId; - if(parentId===childId){ - res[i].children.push(res[j]); - - } - } - } - - // Sort the top-level menu items in order based on the column - res.sort(function(a, b) { - return a.column-b.column; - }); - - // Sort all the children in order based on the column - for(let i = 0; i < res.length; i++){ - res[i].children.sort(function(a, b){ - return a.column-b.column; - }); - } - - //Forming actual parent items - for(let i = 0; i < res.length; i++){ - let parentId=res[i].parentMenuId; - if(parentId===null){ - actualData.push(res[i]); - } - } - - $scope.treedata = actualData; - - }).catch(err => { - $log.error('FunctionalMenuCtrl:getFunctionalMenu:: error ',err); - }).finally(()=> { - this.isLoadingTable = false; - }); - - }; - - - let init = () => { - this.isLoadingTable = false; - this.functionalMenu = []; - getFunctionalMenu(); - this.searchString = ''; - - - }; - - this.filterByDropdownValue = item => { - if(this.filterByApp.value === ''){ - return true; - } - return item.appName === this.filterByApp.value; - }; - - let getDialogTitle = (source) => { - switch (source) { - case 'edit': - return "Functional Menu - Edit"; - case 'view': - return "Functional Menu - View"; - case 'add': - return "Functional Menu - Add"; - default: - return "Functional Menu"; - }; - }; - - $scope.reloadTreeStructure = (selectedItem,source) => { - getFunctionalMenu(); - }; - $scope.openMenuDetailsModal = (selectedItem,source) => { - let data = null; - let selectedMenuDetails = null; - console.log('selectedItem: ', selectedItem); - - functionalMenuService.getMenuDetails(selectedItem.menuId) - .then(function( resp ){ - selectedMenuDetails = resp; - $log.info('FunctionalMenuCtrl::openMenuDetailsModal: getMenuDetails: ', resp ); - - if(selectedItem){ - data = { - menuItem: {menu: _.clone(selectedItem),menuDetails:_.clone(selectedMenuDetails)}, - source: source, - title: getDialogTitle(source) - }; - } - ngDialog.open({ - templateUrl: 'app/views/functionalMenu/functionalMenu-dialog/menu-details.modal.html', - controller: 'MenuDetailsModalCtrl', - controllerAs: 'functionalMenuDetails', - data: data - }).closePromise.then(needUpdate => { - if(needUpdate.value === true){ - $log.debug('FunctionalMenuCtrl::openMenuDetailsModal: updating table data...'); - if(source==="edit") { - init(); - } - } - }); - }); - }; - - - $scope.createNewMenuItem = (selectedItem,source) => { - - if(selectedItem != null && selectedItem.getLevel() >= 4){ - confirmBoxService.showInformation('You are not allowed to have a menu item at a level greater than 4.').then(isConfirmed => { - - }); - return ; - } - - let data = null; - let selectedMenuDetails = null; - functionalMenuService.getMenuDetails(selectedItem.menuId) - .then(function( resp ){ - selectedMenuDetails = resp; - - if((selectedItem.children===null || !selectedItem.children.length>0) && - (!!selectedMenuDetails.url || !!selectedMenuDetails.appid || !!selectedMenuDetails.roles)){ - confirmBoxService.showInformation('Warning: the child menu item "' + selectedItem.name + '" is already configured with an application. You can create a new mid-level menu item, and move this item under it.').then(isConfirmed => { - return; - }); - }else{ - if(selectedItem){ - data = { - menuItem: {menu: _.clone(selectedItem)}, - source:source, - title: getDialogTitle(source) - }; - } - - ngDialog.open({ - templateUrl: 'app/views/functionalMenu/functionalMenu-dialog/menu-details.modal.html', - controller: 'MenuDetailsModalCtrl', - controllerAs: 'functionalMenuDetails', - data: data - }).closePromise.then(needUpdate => { - if(needUpdate.value === true){ - $log.debug('FunctionalMenuCtrl::getMenuDetails: updating table data...'); - init(); - //getOnboardingWidgets(); - } - }); - } - }); - }; - - $scope.deleteMenuItem = (selectedItem,source) => { - $log.info('FunctionalMenuCtrl:deleteMenuItem:: delete selectedItem: ', selectedItem); - - if(selectedItem.children!=null && selectedItem.children.length>0){ - confirmBoxService.showInformation('You are not allowed to delete a menu item that has children. You can only delete leaf menu items.').then(isConfirmed => { - - }); - }else{ - confirmBoxService.deleteItem(selectedItem.name).then(isConfirmed => { - if(isConfirmed){ - $log.info('FunctionalMenuCtrl:deleteMenuItem:: Deleting Menu Item :: name: '+selectedItem.name+'; menuId: '+selectedItem.menuId); - $log.info('FunctionalMenuCtrl:deleteMenuItem:: selectedItem: ', selectedItem); - - functionalMenuService.deleteMenuItem(selectedItem.menuId).then(() => { - //TODO:Have to splice menu item - //this.widgetsList.splice(this.widgetsList.indexOf(widget), 1); - $log.info('FunctionalMenuCtrl:deleteMenuItem:: Removed Menu Item :: '+selectedItem.name); - init(); - }).catch(err => { - $log.error(err); - }); - } - }).catch(err => { - $log.error(err); - }); - } - }; - - init(); - } - } - FunctionalMenuCtrl.$inject = ['$log', 'functionalMenuService','$scope', 'ngDialog', 'confirmBoxService']; - angular.module('ecompApp').controller('FunctionalMenuCtrl', FunctionalMenuCtrl); - - angular.module('ecompApp').directive('jqTree', ['functionalMenuService','$log','confirmBoxService',function(functionalMenuService,$log,confirmBoxService){ - return { - templateUrl: 'jqtree-tmpl.html', - link: function(scope, el, attrs){ - - var $jqTree = el.find('#jqTree').tree({ - data: scope.treedata, - autoOpen: false, - dragAndDrop: true, - onCreateLi: function(node, $li) { - $li.attr('id', node.id.replace(/\s+/g,'_')); - } - }); - - el.find('#jqTree').bind('tree.move', function(event){ - event.preventDefault(); - console.log('moved_node', event.move_info.moved_node); - console.log('target_node', event.move_info.target_node); - console.log('position', event.move_info.position); - console.log('previous_parent', event.move_info.previous_parent); - - - - if(event.move_info.target_node != null && - ((event.move_info.position === 'after' && event.move_info.target_node.getLevel() > 4) || - (event.move_info.position === 'inside' && event.move_info.target_node.getLevel() > 3))){ - confirmBoxService.showInformation('You are not allowed to have a menu item at a level greater than 4.').then(isConfirmed => { - - }); - return ; - } - - var confMsg = 'Are you sure you want to move "'+event.move_info.moved_node.name+'" ?'; - if ((event.move_info.position === "inside") && (event.move_info.target_node.url != "")) { - // If we are moving UNDER a node that has a url associated with it, warn the user - // that all the app information will be removed if they do this. - confMsg = 'Warning: You are moving "'+event.move_info.moved_node.name+'" under "'+event.move_info.target_node.name+'", which has application information associated with it. This will cause all the application information from "'+event.move_info.target_node.name+'" to be deleted.'; - } - confirmBoxService.moveMenuItem(confMsg).then(isConfirmed => { - if(isConfirmed){ - /* - { - "menuId": 129, - "column": 3, - "text": "", - "parentMenuId": 37, - "url": "", - "appid": null, - "roles": null - } - - The menuId for the menu item being moved - The column it is being moved to - The parentMenuId for the parent it is being moved under - */ - - // The target_node is the node before the position we are - // moving to. If we are moving to a lower column number, or - // to a new parent, we must adjust the column to be after - // the target_node. - var new_column = event.move_info.target_node.column; - var old_column = event.move_info.moved_node.column; - if ((event.move_info.moved_node.parentMenuId != - event.move_info.target_node.parentMenuId) || - (new_column < old_column) - ) { - new_column += 1; - } - var activeMenuItem = { - menuId:event.move_info.moved_node.menuId, - column:new_column, - text:"", - parentMenuId:event.move_info.target_node.parentMenuId, - url:"", - appid: null, - roles:null - }; - // When position is "inside", this is a special case, - // where you are moving to the first column under - // a parent. The target_node is the parent node. - // So we need to set the column to 1, and the parentMenuId to the menuId of - // the target move. - if (event.move_info.position === "inside") { - console.log("special case: target_node is parent"); - activeMenuItem.column = 1; - activeMenuItem.parentMenuId = event.move_info.target_node.menuId; - } - - - functionalMenuService.saveEditedMenuItem(activeMenuItem) - .then(() => { - $log.debug(' Menu Item moved'); - scope.reloadTreeStructure(); - }).catch(err => { - $log.error(err); - }).finally(()=>{ - }); - } - }).catch(err => { - $log.error(err); - }); - - //event.move_info.do_move(); - }); - - - $jqTree.jqTreeContextMenu(el.find('ul.dropdown-menu'), { - "view": function (node) {scope.openMenuDetailsModal(node,'view'); }, - "edit": function (node) {scope.openMenuDetailsModal(node,'edit'); }, - "delete": function (node) { scope.deleteMenuItem(node,'delete') }, - "add": function (node) { scope.createNewMenuItem(node,'add') } - }); - - scope.$watch('treedata', function(oldValue, newValue){ - if(oldValue !== newValue){ - console.log('FunctionalMenuCtrl:: Tree value has changed in some way'); - $jqTree.tree('loadData', scope.treedata); - $jqTree.tree('reload', function() { - console.log('FunctionalMenuCtrl:: Tree is reloaded'); - }); - } - }); - } - }; - }]); - -})(); - - +/*- + * ================================================================================ + * 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 FunctionalMenuCtrl { + constructor($log, functionalMenuService, $scope,ngDialog, confirmBoxService) { + $log.info('FunctionalMenuCtrl init'); + + $scope.invokeDialog = () => { + // alert("click dialog"); + }; + + this.regenerateFunctionalMenuAncestors = () => { + functionalMenuService.regenerateFunctionalMenuAncestors().then(res => { + $log.debug("FunctionalMenuCtrl:regenerateFunctionalMenuAncestors::returned from regenerateFunctionalMenuAncestors API call"); + confirmBoxService.showInformation('You have successfully regenerated the menu.').then(isConfirmed => { + }); + })['catch'](function (err) { + $log.error("FunctionalMenuCtrl:regenerateFunctionalMenuAncestors:: error: " + err); + confirmBoxService.showInformation('There was an error while regenerating the menu.').then(isConfirmed => { + }); + }); + }; + + let getFunctionalMenu = () => { + this.isLoadingTable = true; + functionalMenuService.getManagedFunctionalMenu().then(res => { + + let actualData=[]; + + //Adding children and label attribute to all objects in res + for(let i = 0; i < res.length; i++){ + res[i].children=[]; + res[i].label=res[i].text; + res[i].id=res[i].text; + + } + //Adding actual child items to children array in res objects + for(let i = 0; i < res.length; i++){ + + let parentId=res[i].menuId; + for(let j = 0; j < res.length; j++){ + let childId=res[j].parentMenuId; + if(parentId===childId){ + res[i].children.push(res[j]); + + } + } + } + + // Sort the top-level menu items in order based on the column + res.sort(function(a, b) { + return a.column-b.column; + }); + + // Sort all the children in order based on the column + for(let i = 0; i < res.length; i++){ + res[i].children.sort(function(a, b){ + return a.column-b.column; + }); + } + + //Forming actual parent items + for(let i = 0; i < res.length; i++){ + let parentId=res[i].parentMenuId; + if(parentId===null){ + actualData.push(res[i]); + } + } + + $scope.treedata = actualData; + + }).catch(err => { + $log.error('FunctionalMenuCtrl:getFunctionalMenu:: error ',err); + }).finally(()=> { + this.isLoadingTable = false; + }); + + }; + + + let init = () => { + this.isLoadingTable = false; + this.functionalMenu = []; + getFunctionalMenu(); + this.searchString = ''; + + + }; + + this.filterByDropdownValue = item => { + if(this.filterByApp.value === ''){ + return true; + } + return item.appName === this.filterByApp.value; + }; + + let getDialogTitle = (source) => { + switch (source) { + case 'edit': + return "Functional Menu - Edit"; + case 'view': + return "Functional Menu - View"; + case 'add': + return "Functional Menu - Add"; + default: + return "Functional Menu"; + }; + }; + + $scope.reloadTreeStructure = (selectedItem,source) => { + getFunctionalMenu(); + }; + $scope.openMenuDetailsModal = (selectedItem,source) => { + let data = null; + let selectedMenuDetails = null; + console.log('selectedItem: ', selectedItem); + + functionalMenuService.getMenuDetails(selectedItem.menuId) + .then(function( resp ){ + selectedMenuDetails = resp; + $log.info('FunctionalMenuCtrl::openMenuDetailsModal: getMenuDetails: ', resp ); + + if(selectedItem){ + data = { + menuItem: {menu: _.clone(selectedItem),menuDetails:_.clone(selectedMenuDetails)}, + source: source, + title: getDialogTitle(source) + }; + } + ngDialog.open({ + templateUrl: 'app/views/functionalMenu/functionalMenu-dialog/menu-details.modal.html', + controller: 'MenuDetailsModalCtrl', + controllerAs: 'functionalMenuDetails', + data: data + }).closePromise.then(needUpdate => { + if(needUpdate.value === true){ + $log.debug('FunctionalMenuCtrl::openMenuDetailsModal: updating table data...'); + if(source==="edit") { + init(); + } + } + }); + }); + }; + + + $scope.createNewMenuItem = (selectedItem,source) => { + + if(selectedItem != null && selectedItem.getLevel() >= 4){ + confirmBoxService.showInformation('You are not allowed to have a menu item at a level greater than 4.').then(isConfirmed => { + + }); + return ; + } + + let data = null; + let selectedMenuDetails = null; + functionalMenuService.getMenuDetails(selectedItem.menuId) + .then(function( resp ){ + selectedMenuDetails = resp; + + if((selectedItem.children===null || !selectedItem.children.length>0) && + (!!selectedMenuDetails.url || !!selectedMenuDetails.appid || !!selectedMenuDetails.roles)){ + confirmBoxService.showInformation('Warning: the child menu item "' + selectedItem.name + '" is already configured with an application. You can create a new mid-level menu item, and move this item under it.').then(isConfirmed => { + return; + }); + }else{ + if(selectedItem){ + data = { + menuItem: {menu: _.clone(selectedItem)}, + source:source, + title: getDialogTitle(source) + }; + } + + ngDialog.open({ + templateUrl: 'app/views/functionalMenu/functionalMenu-dialog/menu-details.modal.html', + controller: 'MenuDetailsModalCtrl', + controllerAs: 'functionalMenuDetails', + data: data + }).closePromise.then(needUpdate => { + if(needUpdate.value === true){ + $log.debug('FunctionalMenuCtrl::getMenuDetails: updating table data...'); + init(); + //getOnboardingWidgets(); + } + }); + } + }); + }; + + $scope.deleteMenuItem = (selectedItem,source) => { + $log.info('FunctionalMenuCtrl:deleteMenuItem:: delete selectedItem: ', selectedItem); + + if(selectedItem.children!=null && selectedItem.children.length>0){ + confirmBoxService.showInformation('You are not allowed to delete a menu item that has children. You can only delete leaf menu items.').then(isConfirmed => { + + }); + }else{ + confirmBoxService.deleteItem(selectedItem.name).then(isConfirmed => { + if(isConfirmed){ + $log.info('FunctionalMenuCtrl:deleteMenuItem:: Deleting Menu Item :: name: '+selectedItem.name+'; menuId: '+selectedItem.menuId); + $log.info('FunctionalMenuCtrl:deleteMenuItem:: selectedItem: ', selectedItem); + + functionalMenuService.deleteMenuItem(selectedItem.menuId).then(() => { + //TODO:Have to splice menu item + //this.widgetsList.splice(this.widgetsList.indexOf(widget), 1); + $log.info('FunctionalMenuCtrl:deleteMenuItem:: Removed Menu Item :: '+selectedItem.name); + init(); + }).catch(err => { + $log.error(err); + }); + } + }).catch(err => { + $log.error(err); + }); + } + }; + + init(); + } + } + FunctionalMenuCtrl.$inject = ['$log', 'functionalMenuService','$scope', 'ngDialog', 'confirmBoxService']; + angular.module('ecompApp').controller('FunctionalMenuCtrl', FunctionalMenuCtrl); + + angular.module('ecompApp').directive('jqTree', ['functionalMenuService','$log','confirmBoxService',function(functionalMenuService,$log,confirmBoxService){ + return { + templateUrl: 'jqtree-tmpl.html', + link: function(scope, el, attrs){ + + var $jqTree = el.find('#jqTree').tree({ + data: scope.treedata, + autoOpen: false, + dragAndDrop: true, + onCreateLi: function(node, $li) { + $li.attr('id', node.id.replace(/\s+/g,'_')); + } + }); + + el.find('#jqTree').bind('tree.move', function(event){ + event.preventDefault(); + console.log('moved_node', event.move_info.moved_node); + console.log('target_node', event.move_info.target_node); + console.log('position', event.move_info.position); + console.log('previous_parent', event.move_info.previous_parent); + + + + if(event.move_info.target_node != null && + ((event.move_info.position === 'after' && event.move_info.target_node.getLevel() > 4) || + (event.move_info.position === 'inside' && event.move_info.target_node.getLevel() > 3))){ + confirmBoxService.showInformation('You are not allowed to have a menu item at a level greater than 4.').then(isConfirmed => { + + }); + return ; + } + + var confMsg = 'Are you sure you want to move "'+event.move_info.moved_node.name+'" ?'; + if ((event.move_info.position === "inside") && (event.move_info.target_node.url != "")) { + // If we are moving UNDER a node that has a url associated with it, warn the user + // that all the app information will be removed if they do this. + confMsg = 'Warning: You are moving "'+event.move_info.moved_node.name+'" under "'+event.move_info.target_node.name+'", which has application information associated with it. This will cause all the application information from "'+event.move_info.target_node.name+'" to be deleted.'; + } + confirmBoxService.moveMenuItem(confMsg).then(isConfirmed => { + if(isConfirmed){ + /* + { + "menuId": 129, + "column": 3, + "text": "", + "parentMenuId": 37, + "url": "", + "appid": null, + "roles": null + } + + The menuId for the menu item being moved + The column it is being moved to + The parentMenuId for the parent it is being moved under + */ + + // The target_node is the node before the position we are + // moving to. If we are moving to a lower column number, or + // to a new parent, we must adjust the column to be after + // the target_node. + var new_column = event.move_info.target_node.column; + var old_column = event.move_info.moved_node.column; + if ((event.move_info.moved_node.parentMenuId != + event.move_info.target_node.parentMenuId) || + (new_column < old_column) + ) { + new_column += 1; + } + var activeMenuItem = { + menuId:event.move_info.moved_node.menuId, + column:new_column, + text:"", + parentMenuId:event.move_info.target_node.parentMenuId, + url:"", + appid: null, + roles:null + }; + // When position is "inside", this is a special case, + // where you are moving to the first column under + // a parent. The target_node is the parent node. + // So we need to set the column to 1, and the parentMenuId to the menuId of + // the target move. + if (event.move_info.position === "inside") { + console.log("special case: target_node is parent"); + activeMenuItem.column = 1; + activeMenuItem.parentMenuId = event.move_info.target_node.menuId; + } + + + functionalMenuService.saveEditedMenuItem(activeMenuItem) + .then(() => { + $log.debug(' Menu Item moved'); + scope.reloadTreeStructure(); + }).catch(err => { + $log.error(err); + }).finally(()=>{ + }); + } + }).catch(err => { + $log.error(err); + }); + + //event.move_info.do_move(); + }); + + + $jqTree.jqTreeContextMenu(el.find('ul.dropdown-menu'), { + "view": function (node) {scope.openMenuDetailsModal(node,'view'); }, + "edit": function (node) {scope.openMenuDetailsModal(node,'edit'); }, + "delete": function (node) { scope.deleteMenuItem(node,'delete') }, + "add": function (node) { scope.createNewMenuItem(node,'add') } + }); + + scope.$watch('treedata', function(oldValue, newValue){ + if(oldValue !== newValue){ + console.log('FunctionalMenuCtrl:: Tree value has changed in some way'); + $jqTree.tree('loadData', scope.treedata); + $jqTree.tree('reload', function() { + console.log('FunctionalMenuCtrl:: Tree is reloaded'); + }); + } + }); + } + }; + }]); + +})(); + + diff --git a/ecomp-portal-FE-os/client/src/views/functionalMenu/functionalMenu.tpl.html b/ecomp-portal-FE-os/client/src/views/functionalMenu/functionalMenu.tpl.html index 1a1252a1..e71e7a52 100644 --- a/ecomp-portal-FE-os/client/src/views/functionalMenu/functionalMenu.tpl.html +++ b/ecomp-portal-FE-os/client/src/views/functionalMenu/functionalMenu.tpl.html @@ -1,46 +1,46 @@ - -
-
-
-

Edit Functional Menu

-
-
-
-
-
- -
- - Click when you are done with your changes -
-
-
+ +
+
+
+

Edit Functional Menu

+
+
+
+
+
+ +
+ + Click when you are done with your changes +
+
+
diff --git a/ecomp-portal-FE-os/client/src/views/functionalMenu/jqTreeContextMenu.js b/ecomp-portal-FE-os/client/src/views/functionalMenu/jqTreeContextMenu.js index 6e2be32d..dba442c8 100644 --- a/ecomp-portal-FE-os/client/src/views/functionalMenu/jqTreeContextMenu.js +++ b/ecomp-portal-FE-os/client/src/views/functionalMenu/jqTreeContextMenu.js @@ -1,214 +1,214 @@ -/*- - * ================================================================================ - * 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. - * ================================================================================ - */ -(function ($) { - if (!$.fn.tree) { - throw "Error jqTree is not loaded."; - } - - $.fn.jqTreeContextMenu = function (menuElement, callbacks) { - // - // TODO: - // * Make sure the useContextMenu option is set in jqTree, either complain or set it automatically - // * Make menu fade in/out - // - var self = this; - var $el = this; - - // The jQuery object of the menu div. - var $menuEl = menuElement; - - // This hash holds all menu items that should be disabled for a specific node. - var nodeToDisabledMenuItems = {}; - - // Hide the menu div. - $menuEl.hide(); - - // Disable system context menu from beeing displayed. - $el.bind("contextmenu", function (e) { - e.preventDefault(); - return false; - }); - - // Handle the contextmenu event sent from jqTree when user clicks right mouse button. - $el.bind('tree.contextmenu', function (event) { - var x = event.click_event.pageX; - var y = event.click_event.pageY; - var yPadding = 5; - var xPadding = 5; - var menuHeight = $menuEl.height(); - var menuWidth = $menuEl.width(); - var windowHeight = $(window).height(); - var windowWidth = $(window).width(); - - if (menuHeight + y + yPadding > windowHeight) { - // Make sure the whole menu is rendered within the viewport. - y = y - menuHeight; - } - if (menuWidth + x + xPadding > windowWidth) { - // Make sure the whole menu is rendered within the viewport. - x = x - menuWidth; - } - - // Handle disabling and enabling of menu items on specific nodes. - if (Object.keys(nodeToDisabledMenuItems).length > 0) { - if (event.node.name in nodeToDisabledMenuItems) { - var nodeName = event.node.name; - var items = nodeToDisabledMenuItems[nodeName]; - if (items.length === 0) { - $menuEl.find('li').addClass('disabled'); - $menuEl.find('li > a').unbind('click'); - } else { - $menuEl.find('li > a').each(function () { - $(this).closest('li').removeClass('disabled'); - var hrefValue = $(this).attr('href'); - var value = hrefValue.slice(hrefValue.indexOf("#") + 1, hrefValue.length) - if ($.inArray(value, items) > -1) { - $(this).closest('li').addClass('disabled'); - $(this).unbind('click'); - } - }); - } - } else { - $menuEl.find('li.disabled').removeClass('disabled'); - } - } - - // Must call show before we set the offset (offset can not be set on display: none elements). - $menuEl.show(); - - $menuEl.offset({ left: x, top: y }); - - var dismissContextMenu = function () { - $(document).unbind('click.jqtreecontextmenu'); - $el.unbind('tree.click.jqtreecontextmenu'); - $menuEl.hide(); - } - // Make it possible to dismiss context menu by clicking somewhere in the document. - $(document).bind('click.jqtreecontextmenu', function () { - dismissContextMenu(); - }); - - // Dismiss context menu if another node in the tree is clicked. - $el.bind('tree.click.jqtreecontextmenu', function (e) { - dismissContextMenu(); - }); - - // Make selection follow the node that was right clicked on. - var selectedNode = $el.tree('getSelectedNode'); - if (selectedNode !== event.node) { - $el.tree('selectNode', event.node); - } - - // Handle click on menu items, if it's not disabled. - var menuItems = $menuEl.find('li:not(.disabled) a'); - if (menuItems.length !== 0) { - menuItems.unbind('click'); - menuItems.click(function (e) { - e.stopImmediatePropagation(); - dismissContextMenu(); - var hrefAnchor = e.currentTarget.attributes.href.nodeValue; - var funcKey = hrefAnchor.slice(hrefAnchor.indexOf("#") + 1, hrefAnchor.length) - var callbackFn = callbacks[funcKey]; - if (callbackFn) { - callbackFn(event.node); - } - return false; - }); - } - }); - - this.disable = function () { - if (arguments.length === 0) { - // Called as: api.disable() - $menuEl.find('li:not(.disabled)').addClass('disabled'); - $menuEl.find('li a').unbind('click'); - nodeToDisabledMenuItems = {}; - } else if (arguments.length === 1) { - // Called as: api.disable(['edit','remove']) - var items = arguments[0]; - if (typeof items !== 'object') { - return; - } - $menuEl.find('li > a').each(function () { - var hrefValue = $(this).attr('href'); - var value = hrefValue.slice(hrefValue.indexOf("#") + 1, hrefValue.length) - if ($.inArray(value, items) > -1) { - $(this).closest('li').addClass('disabled'); - $(this).unbind('click'); - } - }); - nodeToDisabledMenuItems = {}; - } else if (arguments.length === 2) { - // Called as: api.disable(nodeName, ['edit','remove']) - var nodeName = arguments[0]; - var items = arguments[1]; - nodeToDisabledMenuItems[nodeName] = items; - } - }; - - this.enable = function () { - if (arguments.length === 0) { - // Called as: api.enable() - $menuEl.find('li.disabled').removeClass('disabled'); - nodeToDisabledMenuItems = {}; - } else if (arguments.length === 1) { - // Called as: api.enable(['edit','remove']) - var items = arguments[0]; - if (typeof items !== 'object') { - return; - } - - $menuEl.find('li > a').each(function () { - var hrefValue = $(this).attr('href'); - var value = hrefValue.slice(hrefValue.indexOf("#") + 1, hrefValue.length) - if ($.inArray(value, items) > -1) { - $(this).closest('li').removeClass('disabled'); - } - }); - - nodeToDisabledMenuItems = {}; - } else if (arguments.length === 2) { - // Called as: api.enable(nodeName, ['edit','remove']) - var nodeName = arguments[0]; - var items = arguments[1]; - if (items.length === 0) { - delete nodeToDisabledMenuItems[nodeName]; - } else { - var disabledItems = nodeToDisabledMenuItems[nodeName]; - for (var i = 0; i < items.length; i++) { - var idx = disabledItems.indexOf(items[i]); - if (idx > -1) { - disabledItems.splice(idx, 1); - } - } - if (disabledItems.length === 0) { - delete nodeToDisabledMenuItems[nodeName]; - } else { - nodeToDisabledMenuItems[nodeName] = disabledItems; - } - } - if (Object.keys(nodeToDisabledMenuItems).length === 0) { - $menuEl.find('li.disabled').removeClass('disabled'); - } - } - }; - return this; - }; -} (jQuery)); +/*- + * ================================================================================ + * 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. + * ================================================================================ + */ +(function ($) { + if (!$.fn.tree) { + throw "Error jqTree is not loaded."; + } + + $.fn.jqTreeContextMenu = function (menuElement, callbacks) { + // + // TODO: + // * Make sure the useContextMenu option is set in jqTree, either complain or set it automatically + // * Make menu fade in/out + // + var self = this; + var $el = this; + + // The jQuery object of the menu div. + var $menuEl = menuElement; + + // This hash holds all menu items that should be disabled for a specific node. + var nodeToDisabledMenuItems = {}; + + // Hide the menu div. + $menuEl.hide(); + + // Disable system context menu from beeing displayed. + $el.bind("contextmenu", function (e) { + e.preventDefault(); + return false; + }); + + // Handle the contextmenu event sent from jqTree when user clicks right mouse button. + $el.bind('tree.contextmenu', function (event) { + var x = event.click_event.pageX; + var y = event.click_event.pageY; + var yPadding = 5; + var xPadding = 5; + var menuHeight = $menuEl.height(); + var menuWidth = $menuEl.width(); + var windowHeight = $(window).height(); + var windowWidth = $(window).width(); + + if (menuHeight + y + yPadding > windowHeight) { + // Make sure the whole menu is rendered within the viewport. + y = y - menuHeight; + } + if (menuWidth + x + xPadding > windowWidth) { + // Make sure the whole menu is rendered within the viewport. + x = x - menuWidth; + } + + // Handle disabling and enabling of menu items on specific nodes. + if (Object.keys(nodeToDisabledMenuItems).length > 0) { + if (event.node.name in nodeToDisabledMenuItems) { + var nodeName = event.node.name; + var items = nodeToDisabledMenuItems[nodeName]; + if (items.length === 0) { + $menuEl.find('li').addClass('disabled'); + $menuEl.find('li > a').unbind('click'); + } else { + $menuEl.find('li > a').each(function () { + $(this).closest('li').removeClass('disabled'); + var hrefValue = $(this).attr('href'); + var value = hrefValue.slice(hrefValue.indexOf("#") + 1, hrefValue.length) + if ($.inArray(value, items) > -1) { + $(this).closest('li').addClass('disabled'); + $(this).unbind('click'); + } + }); + } + } else { + $menuEl.find('li.disabled').removeClass('disabled'); + } + } + + // Must call show before we set the offset (offset can not be set on display: none elements). + $menuEl.show(); + + $menuEl.offset({ left: x, top: y }); + + var dismissContextMenu = function () { + $(document).unbind('click.jqtreecontextmenu'); + $el.unbind('tree.click.jqtreecontextmenu'); + $menuEl.hide(); + } + // Make it possible to dismiss context menu by clicking somewhere in the document. + $(document).bind('click.jqtreecontextmenu', function () { + dismissContextMenu(); + }); + + // Dismiss context menu if another node in the tree is clicked. + $el.bind('tree.click.jqtreecontextmenu', function (e) { + dismissContextMenu(); + }); + + // Make selection follow the node that was right clicked on. + var selectedNode = $el.tree('getSelectedNode'); + if (selectedNode !== event.node) { + $el.tree('selectNode', event.node); + } + + // Handle click on menu items, if it's not disabled. + var menuItems = $menuEl.find('li:not(.disabled) a'); + if (menuItems.length !== 0) { + menuItems.unbind('click'); + menuItems.click(function (e) { + e.stopImmediatePropagation(); + dismissContextMenu(); + var hrefAnchor = e.currentTarget.attributes.href.nodeValue; + var funcKey = hrefAnchor.slice(hrefAnchor.indexOf("#") + 1, hrefAnchor.length) + var callbackFn = callbacks[funcKey]; + if (callbackFn) { + callbackFn(event.node); + } + return false; + }); + } + }); + + this.disable = function () { + if (arguments.length === 0) { + // Called as: api.disable() + $menuEl.find('li:not(.disabled)').addClass('disabled'); + $menuEl.find('li a').unbind('click'); + nodeToDisabledMenuItems = {}; + } else if (arguments.length === 1) { + // Called as: api.disable(['edit','remove']) + var items = arguments[0]; + if (typeof items !== 'object') { + return; + } + $menuEl.find('li > a').each(function () { + var hrefValue = $(this).attr('href'); + var value = hrefValue.slice(hrefValue.indexOf("#") + 1, hrefValue.length) + if ($.inArray(value, items) > -1) { + $(this).closest('li').addClass('disabled'); + $(this).unbind('click'); + } + }); + nodeToDisabledMenuItems = {}; + } else if (arguments.length === 2) { + // Called as: api.disable(nodeName, ['edit','remove']) + var nodeName = arguments[0]; + var items = arguments[1]; + nodeToDisabledMenuItems[nodeName] = items; + } + }; + + this.enable = function () { + if (arguments.length === 0) { + // Called as: api.enable() + $menuEl.find('li.disabled').removeClass('disabled'); + nodeToDisabledMenuItems = {}; + } else if (arguments.length === 1) { + // Called as: api.enable(['edit','remove']) + var items = arguments[0]; + if (typeof items !== 'object') { + return; + } + + $menuEl.find('li > a').each(function () { + var hrefValue = $(this).attr('href'); + var value = hrefValue.slice(hrefValue.indexOf("#") + 1, hrefValue.length) + if ($.inArray(value, items) > -1) { + $(this).closest('li').removeClass('disabled'); + } + }); + + nodeToDisabledMenuItems = {}; + } else if (arguments.length === 2) { + // Called as: api.enable(nodeName, ['edit','remove']) + var nodeName = arguments[0]; + var items = arguments[1]; + if (items.length === 0) { + delete nodeToDisabledMenuItems[nodeName]; + } else { + var disabledItems = nodeToDisabledMenuItems[nodeName]; + for (var i = 0; i < items.length; i++) { + var idx = disabledItems.indexOf(items[i]); + if (idx > -1) { + disabledItems.splice(idx, 1); + } + } + if (disabledItems.length === 0) { + delete nodeToDisabledMenuItems[nodeName]; + } else { + nodeToDisabledMenuItems[nodeName] = disabledItems; + } + } + if (Object.keys(nodeToDisabledMenuItems).length === 0) { + $menuEl.find('li.disabled').removeClass('disabled'); + } + } + }; + return this; + }; +} (jQuery)); diff --git a/ecomp-portal-FE-os/client/src/views/header/header-extension.tpl.html b/ecomp-portal-FE-os/client/src/views/header/header-extension.tpl.html new file mode 100644 index 00000000..8c7ee407 --- /dev/null +++ b/ecomp-portal-FE-os/client/src/views/header/header-extension.tpl.html @@ -0,0 +1,3 @@ + \ No newline at end of file diff --git a/ecomp-portal-FE-os/client/src/views/header/header-logo.html b/ecomp-portal-FE-os/client/src/views/header/header-logo.html new file mode 100644 index 00000000..0ab0560e --- /dev/null +++ b/ecomp-portal-FE-os/client/src/views/header/header-logo.html @@ -0,0 +1 @@ + diff --git a/ecomp-portal-FE-os/client/src/views/header/profile-edit-dialogs/profile-edit.controller.js b/ecomp-portal-FE-os/client/src/views/header/profile-edit-dialogs/profile-edit.controller.js new file mode 100644 index 00000000..4720e752 --- /dev/null +++ b/ecomp-portal-FE-os/client/src/views/header/profile-edit-dialogs/profile-edit.controller.js @@ -0,0 +1,87 @@ +/*- + * ================================================================================ + * 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 EditProfileModalCtrl { + constructor($log,ngDialog,usersService,confirmBoxService,adminsService) { + this.firstName =''; + this.middleName =''; + this.lastName =''; + this.email =''; + this.loginId =''; + this.loginPwd =''; + this.confirmLoginPwd='' + this.isLoading = false; + let getUser = () => { + this.isLoading = true; + usersService.getLoggedInUser() + .then(user=> { + var data = user.response; + console.log(data); + this.firstName =data.firstName; + this.middleName =data.middleName; + this.lastName =data.lastName; + this.email =data.email; + this.loginId =data.loginId; + this.loginPwd =data.loginPassword; + this.isLoading = false; + }).catch(err=> { + $log.error('EditProfileModalCtrl.getUser:: Error retrieving ECMOP portal user: ' + err); + }); + } + getUser(); + + this.save = ()=>{ + var profileDetail ={ + firstName : this.firstName, + middleName :this.middleName, + lastName :this.lastName, + email :this.email, + loginId :this.loginId, + loginPassword :this.loginPwd + } + if (this.firstName =='' || this.lastName == '' || this.email == '' || this.loginId =='' || this.loginPwd ==''|| this.confirmLoginPwd ==''){ + var warningMsg = "Please enter a value for all fields marked with *."; + confirmBoxService.showInformation(warningMsg).then(isConfirmed => {return;}); + return; + } else if (this.loginPwd != this.confirmLoginPwd) { + var warningMsg = "Passwords do not match, please try again."; + confirmBoxService.showInformation(warningMsg).then(isConfirmed => {return;}); + return; + } else { + // check password length complexity. + var warningMsg = adminsService.isComplexPassword(this.loginPwd); + if (warningMsg != null) { + confirmBoxService.showInformation(warningMsg).then(isConfirmed => {return;}); + return; + } + } + usersService.modifyLoggedInUser(profileDetail).then(res=> { + confirmBoxService.showInformation("Profile detail updated").then(isConfirmed => {return;}); + }).catch(err=> { + $log.error('EditProfileModalCtrl.getUser:: Error retrieving ECMOP portal user: ' + err); + confirmBoxService.showInformation("Error while updating profile detail: "+ err).then(isConfirmed => {return;}); + }); + } + } + } + EditProfileModalCtrl.$inject = ['$log', 'ngDialog','usersService','confirmBoxService','adminsService']; + angular.module('ecompApp').controller('EditProfileModalCtrl', EditProfileModalCtrl); +})(); diff --git a/ecomp-portal-FE-os/client/src/views/header/profile-edit-dialogs/profile-edit.modal.html b/ecomp-portal-FE-os/client/src/views/header/profile-edit-dialogs/profile-edit.modal.html new file mode 100644 index 00000000..cfe5a15d --- /dev/null +++ b/ecomp-portal-FE-os/client/src/views/header/profile-edit-dialogs/profile-edit.modal.html @@ -0,0 +1,69 @@ + +
+
+
Profile Detail
+ + +
+
+
+
+
*First Name
+ +
+
+
Middle Name
+ +
+
+
*Last Name
+ +
+
+
*Email Address ID
+ +
+
+
*Login ID
+ +
+
+
*Login Password
+ +
+
+
*Confirm Login Password
+ +
+
+
+
+ + + +
+
+
+
diff --git a/ecomp-portal-FE-os/client/src/views/header/profile-edit-dialogs/profile-edit.modal.less b/ecomp-portal-FE-os/client/src/views/header/profile-edit-dialogs/profile-edit.modal.less new file mode 100644 index 00000000..b103f304 --- /dev/null +++ b/ecomp-portal-FE-os/client/src/views/header/profile-edit-dialogs/profile-edit.modal.less @@ -0,0 +1,21 @@ +.profile-detail-modal { + height: 430px; + margin-left: 20px; + + .prodile-detail { + .title { + //.n18r; + .dGray18r; + border-bottom: @blue-active 3px solid; + + } + } + + + .profile-edit-div{ + display: inline-block; + width: 240px; + margin-left: 10px; + } +} + diff --git a/ecomp-portal-FE-os/client/src/views/search/search.controller.js b/ecomp-portal-FE-os/client/src/views/search/search.controller.js index 3c3c2a03..3cb22bfd 100644 --- a/ecomp-portal-FE-os/client/src/views/search/search.controller.js +++ b/ecomp-portal-FE-os/client/src/views/search/search.controller.js @@ -1,198 +1,198 @@ -/*- - * ================================================================================ - * 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 SearchCtrl { - constructor($log, $scope, $cookies, $timeout, userProfileService, sessionService, dashboardService) { - $scope.firstName=""; - $scope.lastName=""; - - function showHideSearchSnippet() { - - setTimeout(function() { - jQuery("#mainSearchSnippet").click(); - },500); - - setTimeout(function() { - jQuery("#mainSearchText").focus(); - },1000); - } - - jQuery("#mainSearchDiv").keyup(function(event){ - if(event.keyCode == 13){ - // there is a watch on this variable which will trigger the database pull - dashboardService.searchString = jQuery("#mainSearchText").val(); - - // opens the popup - var popupDomObj = jQuery("[content='searchSnippet.html']"); - if(popupDomObj.length == 0) { - showHideSearchSnippet(); - } else { - jQuery("#mainSearchSnippet").click(); - showHideSearchSnippet(); - } - - - - } - }); - - - - } - - - } - - - class SearchSnippetCtrl { - constructor($log, $scope, $cookies, $timeout, userProfileService, sessionService, dashboardService,applicationsService, $window, $state) { - $scope.firstName=""; - $scope.lastName=""; - $scope.goToUrl = goToUrl; - $scope.dService = dashboardService; - - $scope.searchResDialog = false; - $scope.searchDialogToggle = function($event){ - var keyCode = $event.which || $event.keyCode; - if (keyCode === 13) { - $scope.searchResDialog = true; - dashboardService.searchString = jQuery("#mainSearchText").val(); - } - - } - - window.onclick = function() { - if ($scope.searchResDialog) { - $scope.searchResDialog = false; - $scope.$apply(); - } - }; - function goToUrl (item, type) { - $log.info("goToUrl called") - $log.info(item + "/" + type); - - - if(type == 'intra') { - - var intraSearcLink = ""; - var intraSpecSearcLink = intraSearcLink + encodeURIComponent(dashboardService.searchString); - $window.open(intraSpecSearcLink, '_blank'); - - } else if (type == 'extra') { - var extraSearcLink = ""; - var extraSpecSearcLink = extraSearcLink + encodeURIComponent(dashboardService.searchString); - $window.open(extraSpecSearcLink, '_blank'); - } - - let url = item.target; - let restrictedApp = item.uuid; - let getAccessState = "root.getAccess" - if (!url) { - - applicationsService.goGetAccessAppName = item.name; - if($state.current.name == getAccessState) - $state.reload(); - else - $state.go(getAccessState); - //$log.info('No url found for this application, doing nothing..'); - return; - } - - if (restrictedApp != "true") { - $window.open(url, '_blank'); - } else { - if(item.url=="root.access"){ - $state.go(url); - var tabContent = { id: new Date(), title: 'Home', url: url }; - $cookies.putObject('addTab', tabContent ); - } else { - var tabContent = { id: new Date(), title: item.name, url: url }; - $cookies.putObject('addTab', tabContent ); - } - } - - } - - function getItems(searchString) { - - var items; - var itemMap = dashboardService.getSearchAllByStringResults(searchString) - .then(res => { - $scope.items = res; - - - }).catch(err => { - $scope.items = []; - $log.error('Couldnt get search results...', err) - }); - - } - - $scope.$watch('dService.searchString', function(searchString) { - if(searchString != undefined ) - getItems(searchString); - - }); - - - - } - - - - } - - - - SearchCtrl.$inject = ['$log', '$scope', '$cookies', '$timeout','userProfileService', 'sessionService', 'dashboardService']; - SearchSnippetCtrl.$inject = ['$log', '$scope', '$cookies', '$timeout','userProfileService', 'sessionService', 'dashboardService','applicationsService', '$window','$state']; - angular.module('ecompApp').controller('searchCtrl', SearchCtrl); - angular.module('ecompApp').controller('searchSnippetCtrl', SearchSnippetCtrl); - angular.module('ecompApp').directive('searchBox', function() { - return { - restrict: "E", - templateUrl: 'app/views/search/search.tpl.html', - link: function(scope, element) { - - //var iframeId = "#tabframe-" + scope.$parent.tab.title.split(' ').join('-'); - // jQuery(iframeId).load(function() { - // alert("hello"); - // }); //.attr("src",'{{tab.content | trusted}}' ); //src='{{tab.content | trusted}}' - // jQuery(iframeId).attr('src', '{{tab.content | trusted}}'); - - //element.childNodes[0].on('load', function() { - // alert('hello'); - //}); - } - } - }); - angular.module( 'ecompApp' ).config( [ - '$compileProvider', - function( $compileProvider ) - { - $compileProvider.aHrefSanitizationWhitelist(/^\s*(https?|ftp|mailto|chrome-extension|qto):/); - } - ]); - -})(); - - +/*- + * ================================================================================ + * 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 SearchCtrl { + constructor($log, $scope, $cookies, $timeout, userProfileService, sessionService, dashboardService) { + $scope.firstName=""; + $scope.lastName=""; + + function showHideSearchSnippet() { + + setTimeout(function() { + jQuery("#mainSearchSnippet").click(); + },500); + + setTimeout(function() { + jQuery("#mainSearchText").focus(); + },1000); + } + + jQuery("#mainSearchDiv").keyup(function(event){ + if(event.keyCode == 13){ + // there is a watch on this variable which will trigger the database pull + dashboardService.searchString = jQuery("#mainSearchText").val(); + + // opens the popup + var popupDomObj = jQuery("[content='searchSnippet.html']"); + if(popupDomObj.length == 0) { + showHideSearchSnippet(); + } else { + jQuery("#mainSearchSnippet").click(); + showHideSearchSnippet(); + } + + + + } + }); + + + + } + + + } + + + class SearchSnippetCtrl { + constructor($log, $scope, $cookies, $timeout, userProfileService, sessionService, dashboardService,applicationsService, $window, $state) { + $scope.firstName=""; + $scope.lastName=""; + $scope.goToUrl = goToUrl; + $scope.dService = dashboardService; + + $scope.searchResDialog = false; + $scope.searchDialogToggle = function($event){ + var keyCode = $event.which || $event.keyCode; + if (keyCode === 13) { + $scope.searchResDialog = true; + dashboardService.searchString = jQuery("#mainSearchText").val(); + } + + } + + window.onclick = function() { + if ($scope.searchResDialog) { + $scope.searchResDialog = false; + $scope.$apply(); + } + }; + function goToUrl (item, type) { + $log.info("goToUrl called") + $log.info(item + "/" + type); + + + if(type == 'intra') { + + var intraSearcLink = ""; + var intraSpecSearcLink = intraSearcLink + encodeURIComponent(dashboardService.searchString); + $window.open(intraSpecSearcLink, '_blank'); + + } else if (type == 'extra') { + var extraSearcLink = ""; + var extraSpecSearcLink = extraSearcLink + encodeURIComponent(dashboardService.searchString); + $window.open(extraSpecSearcLink, '_blank'); + } + + let url = item.target; + let restrictedApp = item.uuid; + let getAccessState = "root.getAccess" + if (!url) { + + applicationsService.goGetAccessAppName = item.name; + if($state.current.name == getAccessState) + $state.reload(); + else + $state.go(getAccessState); + //$log.info('No url found for this application, doing nothing..'); + return; + } + + if (restrictedApp != "true") { + $window.open(url, '_blank'); + } else { + if(item.url=="root.access"){ + $state.go(url); + var tabContent = { id: new Date(), title: 'Home', url: url }; + $cookies.putObject('addTab', tabContent ); + } else { + var tabContent = { id: new Date(), title: item.name, url: url }; + $cookies.putObject('addTab', tabContent ); + } + } + + } + + function getItems(searchString) { + + var items; + var itemMap = dashboardService.getSearchAllByStringResults(searchString) + .then(res => { + $scope.items = res; + + + }).catch(err => { + $scope.items = []; + $log.error('Couldnt get search results...', err) + }); + + } + + $scope.$watch('dService.searchString', function(searchString) { + if(searchString != undefined ) + getItems(searchString); + + }); + + + + } + + + + } + + + + SearchCtrl.$inject = ['$log', '$scope', '$cookies', '$timeout','userProfileService', 'sessionService', 'dashboardService']; + SearchSnippetCtrl.$inject = ['$log', '$scope', '$cookies', '$timeout','userProfileService', 'sessionService', 'dashboardService','applicationsService', '$window','$state']; + angular.module('ecompApp').controller('searchCtrl', SearchCtrl); + angular.module('ecompApp').controller('searchSnippetCtrl', SearchSnippetCtrl); + angular.module('ecompApp').directive('searchBox', function() { + return { + restrict: "E", + templateUrl: 'app/views/search/search.tpl.html', + link: function(scope, element) { + + //var iframeId = "#tabframe-" + scope.$parent.tab.title.split(' ').join('-'); + // jQuery(iframeId).load(function() { + // alert("hello"); + // }); //.attr("src",'{{tab.content | trusted}}' ); //src='{{tab.content | trusted}}' + // jQuery(iframeId).attr('src', '{{tab.content | trusted}}'); + + //element.childNodes[0].on('load', function() { + // alert('hello'); + //}); + } + } + }); + angular.module( 'ecompApp' ).config( [ + '$compileProvider', + function( $compileProvider ) + { + $compileProvider.aHrefSanitizationWhitelist(/^\s*(https?|ftp|mailto|chrome-extension|qto):/); + } + ]); + +})(); + + diff --git a/ecomp-portal-FE-os/client/src/views/search/search.controller.spec.js b/ecomp-portal-FE-os/client/src/views/search/search.controller.spec.js index 3841a2b3..32cc3a1f 100644 --- a/ecomp-portal-FE-os/client/src/views/search/search.controller.spec.js +++ b/ecomp-portal-FE-os/client/src/views/search/search.controller.spec.js @@ -1,19 +1,19 @@ -/*- - * ================================================================================ - * 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. - * ================================================================================ - */ +/*- + * ================================================================================ + * 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. + * ================================================================================ + */ diff --git a/ecomp-portal-FE-os/client/src/views/support/contact-us/contact-us.aux.html b/ecomp-portal-FE-os/client/src/views/support/contact-us/contact-us.aux.html index 822c5099..c65fb69e 100644 --- a/ecomp-portal-FE-os/client/src/views/support/contact-us/contact-us.aux.html +++ b/ecomp-portal-FE-os/client/src/views/support/contact-us/contact-us.aux.html @@ -1,25 +1,25 @@ - -
- To give feedback or report an issue - to the OpenECOMP Portal team, send email to {{contact.portalInfo_Address}}. - -
+ +
+ To give feedback or report an issue + to the OpenECOMP Portal team, send email to {{contact.portalInfo_Address}}. + +
diff --git a/ecomp-portal-FE-os/client/src/views/support/get-access/get-accessinfo.html b/ecomp-portal-FE-os/client/src/views/support/get-access/get-accessinfo.html index a8a42c1d..33fb8a5d 100644 --- a/ecomp-portal-FE-os/client/src/views/support/get-access/get-accessinfo.html +++ b/ecomp-portal-FE-os/client/src/views/support/get-access/get-accessinfo.html @@ -1,24 +1,24 @@ - -
- Request access for following functions by sending email to the Application's Admin. For Admin contact details, please - click here. - -
+ +
+ Request access for following functions by sending email to the Application's Admin. For Admin contact details, please + click here. + +
diff --git a/ecomp-portal-FE-os/client/src/views/userbar/userbar.tpl.html b/ecomp-portal-FE-os/client/src/views/userbar/userbar.tpl.html index b40a1748..669de8c5 100644 --- a/ecomp-portal-FE-os/client/src/views/userbar/userbar.tpl.html +++ b/ecomp-portal-FE-os/client/src/views/userbar/userbar.tpl.html @@ -1,20 +1,20 @@ - - + + -- cgit 1.2.3-korg
ThumbnailApplication NameApplication Name Active? Integration Type Guest Access