summaryrefslogtreecommitdiffstats
path: root/ecomp-portal-FE/client/app/directives
diff options
context:
space:
mode:
Diffstat (limited to 'ecomp-portal-FE/client/app/directives')
-rw-r--r--ecomp-portal-FE/client/app/directives/auto-focus/auto-focus.directive.js46
-rw-r--r--ecomp-portal-FE/client/app/directives/image-upload/image-upload.directive.js222
-rw-r--r--ecomp-portal-FE/client/app/directives/left-menu/left-menu.directive.js96
-rw-r--r--ecomp-portal-FE/client/app/directives/left-menu/left-menu.less133
-rw-r--r--ecomp-portal-FE/client/app/directives/left-menu/left-menu.tpl.html57
-rw-r--r--ecomp-portal-FE/client/app/directives/multiple-select/multiple-select.directive.js111
-rw-r--r--ecomp-portal-FE/client/app/directives/multiple-select/multiple-select.less81
-rw-r--r--ecomp-portal-FE/client/app/directives/multiple-select/multiple-select.tpl.html38
-rw-r--r--ecomp-portal-FE/client/app/directives/right-click-menu/right-click-menu.directive.js38
-rw-r--r--ecomp-portal-FE/client/app/directives/right-click/ng-right-click-directive.js32
-rw-r--r--ecomp-portal-FE/client/app/directives/right-menu/right-menu.directive.js140
-rw-r--r--ecomp-portal-FE/client/app/directives/right-menu/right-menu.less178
-rw-r--r--ecomp-portal-FE/client/app/directives/right-menu/right-menu.tpl.html40
-rw-r--r--ecomp-portal-FE/client/app/directives/scroll-top/scroll-top.directive.js35
-rw-r--r--ecomp-portal-FE/client/app/directives/search-users/search-users.controller.js161
-rw-r--r--ecomp-portal-FE/client/app/directives/search-users/search-users.controller.spec.js176
-rw-r--r--ecomp-portal-FE/client/app/directives/search-users/search-users.directive.js34
-rw-r--r--ecomp-portal-FE/client/app/directives/search-users/search-users.less154
-rw-r--r--ecomp-portal-FE/client/app/directives/search-users/search-users.tpl.html144
19 files changed, 1916 insertions, 0 deletions
diff --git a/ecomp-portal-FE/client/app/directives/auto-focus/auto-focus.directive.js b/ecomp-portal-FE/client/app/directives/auto-focus/auto-focus.directive.js
new file mode 100644
index 00000000..73964115
--- /dev/null
+++ b/ecomp-portal-FE/client/app/directives/auto-focus/auto-focus.directive.js
@@ -0,0 +1,46 @@
+/*-
+ * ================================================================================
+ * 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.
+ * ================================================================================
+ */
+
+
+
+//angular.module('ecompApp')
+// .directive('autoFocus', function () {
+// return {
+// restrict: 'A',
+// scope: {},
+// link: function (scope, element) {
+// element[0].focus();
+// }
+// };
+// });
+
+/* istanbul ignore next */
+(function(){
+ class AutoFocusDirective{
+ constructor(){
+ this.restrict = 'A';
+ this.link = this._link.bind(this);
+ }
+ _link(scope, element){
+ element[0].focus();
+ }
+ }
+ angular.module('ecompApp').directive('autoFocus', () => new AutoFocusDirective());
+})();
diff --git a/ecomp-portal-FE/client/app/directives/image-upload/image-upload.directive.js b/ecomp-portal-FE/client/app/directives/image-upload/image-upload.directive.js
new file mode 100644
index 00000000..90c88c50
--- /dev/null
+++ b/ecomp-portal-FE/client/app/directives/image-upload/image-upload.directive.js
@@ -0,0 +1,222 @@
+/*-
+ * ================================================================================
+ * 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';
+
+angular.module('ecompApp').directive('imageUpload', function factory($q) {
+ var imageMimeRgx = /^image\/[a-zA-Z0-9]*$/;
+
+ var URL = window.URL || window.webkitURL;
+
+ var getResizeArea = function () {
+ var resizeAreaId = 'fileupload-resize-area';
+
+ var resizeArea = document.getElementById(resizeAreaId);
+
+ if (!resizeArea) {
+ resizeArea = document.createElement('canvas');
+ resizeArea.id = resizeAreaId;
+ resizeArea.style.visibility = 'hidden';
+ document.body.appendChild(resizeArea);
+ }
+
+ return resizeArea;
+ };
+
+ var resizeImage = function (origImage, options) {
+ var maxHeight = options.resizeMaxHeight || 300;
+ var maxWidth = options.resizeMaxWidth || 250;
+ var quality = options.resizeQuality || 0.7;
+ var type = options.resizeType || 'image/jpg';
+
+ var canvas = getResizeArea();
+
+ var height = origImage.height;
+ var width = origImage.width;
+
+ //image redraw starting points
+ var x0, y0;
+
+ // calculate the width and height, constraining the proportions
+ if (width > height) {
+ if (width > maxWidth) {
+ height = Math.round(height *= maxWidth / width);
+ width = maxWidth;
+
+ x0 = 0;
+ y0 = Math.round((maxHeight - height)/2);
+ }else{
+ maxHeight = height;
+ maxWidth = width;
+ x0 = 0;
+ y0 = 0;
+ }
+ } else {
+ if (height > maxHeight) {
+ width = Math.round(width *= maxHeight / height);
+ height = maxHeight;
+
+ x0 = Math.round((maxWidth - width)/2);
+ y0 = 0;
+ }else{
+ maxHeight = height;
+ maxWidth = width;
+ x0 = 0;
+ y0 = 0;
+ }
+ }
+
+ canvas.width = maxWidth;
+ canvas.height = maxHeight;
+
+ //draw image on canvas
+ var ctx = canvas.getContext("2d");
+
+ //set background color
+ if(options.backgroundColor){
+ ctx.fillStyle = options.backgroundColor;
+ ctx.fillRect(0,0,maxWidth,maxHeight);
+ }
+
+
+ ctx.drawImage(origImage, x0, y0, width, height);
+
+ // get the data from canvas as 70% jpg (or specified type).
+ return canvas.toDataURL(type, quality);
+ };
+
+ var createImage = function(url, callback) {
+ var image = new Image();
+ image.onload = function() {
+ callback(image);
+ };
+ image.src = url;
+ };
+
+ var fileToDataURL = function (file) {
+ var deferred = $q.defer();
+ var reader = new FileReader();
+ reader.onload = function (e) {
+ deferred.resolve(e.target.result);
+ };
+ reader.readAsDataURL(file);
+ return deferred.promise;
+ };
+
+ return {
+ restrict: 'A',
+ require: '^form',
+ scope: {
+ image: '=imageUpload',
+ resizeMaxHeight: '@?imageUploadResizeMaxHeight',
+ resizeMaxWidth: '@?imageUploadResizeMaxWidth',
+ resizeQuality: '@?imageUploadResizeQuality',
+ resizeType: '@?imageUploadResizeType',
+ imageApi: '=?imageUploadApi',
+ backgroundColor: '@?imageUploadBackgroundColor'
+ },
+ compile: function compile(tElement, tAttrs, transclude) {
+ return function postLink(scope, iElement, iAttrs, formCtrl) {
+ var doResizing = function(imageResult, callback) {
+ createImage(imageResult.url, function(image) {
+ var dataURL = resizeImage(image, scope);
+ imageResult.resized = {
+ dataURL: dataURL,
+ type: dataURL.match(/:(.+\/.+);/)[1]
+ };
+ callback(imageResult);
+ });
+ };
+
+ var applyScope = function(imageResult) {
+ scope.$apply(function() {
+ //console.log(imageResult);
+ if(iAttrs.multiple)
+ scope.image.push(imageResult);
+ else
+ scope.image = imageResult;
+ });
+ };
+
+ iElement.bind('change', function (evt) {
+ //when multiple always return an array of images
+ if(iAttrs.multiple)
+ scope.image = [];
+
+ var files = evt.target.files;
+ for(var i = 0; i < files.length; i++) {
+ setInputValidity(files[i]);
+
+ //create a result object for each file in files
+ var imageResult = {
+ file: files[i],
+ url: URL.createObjectURL(files[i])
+ };
+
+ fileToDataURL(files[i]).then(function (dataURL) {
+ imageResult.dataURL = dataURL;
+ });
+
+ if(scope.resizeMaxHeight || scope.resizeMaxWidth) { //resize image
+ doResizing(imageResult, function(imageResult) {
+ applyScope(imageResult);
+ });
+ }
+ else { //no resizing
+ applyScope(imageResult);
+ }
+ }
+ });
+
+ //API for otter actions
+ scope.imageApi = scope.imageApi || {};
+ scope.imageApi.clearFile = () => {
+ iElement[0].value = "";
+ setInputValidity();
+ };
+
+
+ let setInputValidity = file => {
+ //if form validation supported
+
+ if(formCtrl && iAttrs.name && formCtrl[iAttrs.name]){
+ formCtrl[iAttrs.name].$setDirty();
+ if(file && file.type && !imageMimeRgx.test(file.type)){
+ //set form invalid
+ formCtrl[iAttrs.name].$setValidity('mimeType', false);
+ applyScope();
+ return;
+ }
+ if(file && file.size && file.size > 1000000){
+ //set form invalid
+ formCtrl[iAttrs.name].$setValidity('imageSize', false);
+ applyScope();
+ return;
+ }
+ //set valid
+ formCtrl[iAttrs.name].$setValidity('mimeType', true);
+ formCtrl[iAttrs.name].$setValidity('imageSize', true);
+ }
+
+ }
+ }
+ }
+ }
+});
diff --git a/ecomp-portal-FE/client/app/directives/left-menu/left-menu.directive.js b/ecomp-portal-FE/client/app/directives/left-menu/left-menu.directive.js
new file mode 100644
index 00000000..363485fe
--- /dev/null
+++ b/ecomp-portal-FE/client/app/directives/left-menu/left-menu.directive.js
@@ -0,0 +1,96 @@
+/*-
+ * ================================================================================
+ * 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 () {
+ class LeftMenu {
+ constructor($rootScope, $log, userbarUpdateService) {
+ this.templateUrl = 'app/directives/left-menu/left-menu.tpl.html';
+ this.restrict = 'AE';
+ this.$rootScope = $rootScope;
+ this.$log = $log;
+ this.userbarUpdateService = userbarUpdateService;
+ this.link = this._link.bind(this);
+ this.scope = {
+ sidebarModel: '='
+ }
+ }
+
+ _link(scope) {
+ let init = () => {
+ scope.isOpen = true;
+ };
+
+ init();
+
+ scope.refreshOnlineUsers = () => {
+ this.userbarUpdateService.setRefreshCount(this.userbarUpdateService.maxCount);
+ };
+
+ scope.toggleSidebar = () => {
+ scope.isOpen = !scope.isOpen;
+ if(scope.isOpen)
+ setContentPos(1);
+ else
+ setContentPos(0);
+
+ };
+
+ scope.isBrowserInternetExplorer = false;
+ scope.browserName = bowser.name;
+
+ if (bowser.msie || bowser.msedge) {
+ scope.isBrowserInternetExplorer = true;
+ } else {
+ scope.isBrowserInternetExplorer = false;
+ }
+
+ let log = this.$log;
+
+ this.userbarUpdateService.getWidthThresholdLeftMenu().then(function (res) {
+ if (res == null || res.response == null) {
+ log.error('userbarUpdateService: failed to get window width threshold for collapsing left menu; please make sure "window_width_threshold_left_menu" is specified in system.properties file.');
+ } else {
+ var leftMenuCollapseWidthThreshold = parseInt(res.response.windowWidth);
+ if ($(window).width()<leftMenuCollapseWidthThreshold) {
+ scope.toggleSidebar();
+ }
+ }
+ })['catch'](function (err) {
+ log.error('LeftMenu Controller:: getWidthThresholdLeftMenu() failed: ' + err);
+ });
+
+
+
+ this.$rootScope.$on('$stateChangeStart', () => {
+ scope.isOpen = true;
+ });
+ }
+ }
+ angular.module('ecompApp').directive('leftMenu', ($rootScope,$log,userbarUpdateService) => new LeftMenu($rootScope,$log,userbarUpdateService));
+})();
+
+function setContentPos(open) {
+ if(open==1){
+ $("#contentId" ).css( "padding-left", "210px" );
+ }else{
+ $("#contentId" ).css( "padding-left", "50px" );
+ }
+
+}
diff --git a/ecomp-portal-FE/client/app/directives/left-menu/left-menu.less b/ecomp-portal-FE/client/app/directives/left-menu/left-menu.less
new file mode 100644
index 00000000..276fb409
--- /dev/null
+++ b/ecomp-portal-FE/client/app/directives/left-menu/left-menu.less
@@ -0,0 +1,133 @@
+/*-
+ * ================================================================================
+ * 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.
+ * ================================================================================
+ */
+@sidebar-width: 200px;
+@transition-duration: 0.25s;
+@overlayer-opacity: 0.65;
+
+
+.close-button {
+ .a24r;
+ font-size: 3em;
+ line-height: 18px;
+ position: absolute;
+ cursor: pointer;
+ vertical-align: middle;
+ top: @second-level-top;
+ left: 0;
+ -webkit-font-smoothing: antialiased;
+ height: 53px;
+ z-index: 101;
+}
+.ecomp-sidebar-container {
+ position: absolute;
+ display: block;
+ left: 0;
+ z-index: 100;
+ transition: left @transition-duration;
+ margin-top: -15px;
+
+ .ecomp-sidebar-main {
+ position: absolute;
+ margin-top: 65px;
+ width: @sidebar-width;
+ height: 100vh;
+ .bg_u;
+ box-shadow: 0 4px 5px rgba(0, 0, 0, .2);
+
+ padding-right: 10px;
+ padding-left: 10px;
+
+ .accordion-container{
+ margin-top: 45px;
+ overflow-y:auto;
+ overflow-x:hidden;
+ }
+ .att-accordion-font{
+ font-size: .875rem;
+ color: #666;
+ display: inline-block;
+ font-family: arial;
+
+ }
+
+ .att-accordion-active{
+ color: #199DDF !important;
+ }
+
+ .sub-item{
+ .att-accordion-font;
+ cursor: pointer;
+ height: 37px;
+ line-height: 37px;
+ padding-left: 20px;
+ padding-bottom: 10px;
+ vertical-align: middle;
+ width: 100%;
+ }
+ .sub-item:hover{
+ .att-accordion-active;
+ }
+
+ .parent-item{
+ .att-accordion-font;
+ border-bottom: 1px solid #bbb;
+ cursor: pointer;
+ height: 37px;
+ line-height: 37px;
+ padding-bottom: 10px;
+ vertical-align: middle;
+ width: 100%;
+ }
+ .parent-item:hover{
+ .att-accordion-active;
+ }
+
+ }
+}
+
+.open-sidebar {
+ left: 0;
+}
+
+.close-sidebar {
+ left: -@sidebar-width;
+}
+
+.content-overlayed {
+ position: fixed;
+ top: 110px;
+ right: 0;
+ bottom: 0;
+ left: 0;
+ background: none repeat scroll 0 0 rgb(242, 242, 242);
+ z-index: 9999;
+}
+.fade-animation{
+ opacity: @overlayer-opacity;
+ transition: opacity @transition-duration ease-in-out;
+}
+.fade-animation.ng-hide {
+ opacity:0;
+ transition: opacity @transition-duration ease-in-out;
+}
+
+#contentId{
+ padding-left:210px
+} \ No newline at end of file
diff --git a/ecomp-portal-FE/client/app/directives/left-menu/left-menu.tpl.html b/ecomp-portal-FE/client/app/directives/left-menu/left-menu.tpl.html
new file mode 100644
index 00000000..0059d6a4
--- /dev/null
+++ b/ecomp-portal-FE/client/app/directives/left-menu/left-menu.tpl.html
@@ -0,0 +1,57 @@
+<!--
+ ================================================================================
+ eCOMP Portal
+ ================================================================================
+ Copyright (C) 2017 AT&T Intellectual Property
+ ================================================================================
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ ================================================================================
+ -->
+<div class="close-button" ng-click="toggleSidebar()">
+ <span id="icon-hamburger" class="ion-navicon-round" ></span>
+</div>
+<div id="ecomp-sidebar-container" class="ecomp-sidebar-container" ng-class="isOpen ? 'open-sidebar': 'close-sidebar'">
+ <div class="ecomp-sidebar-main" >
+ <div class="accordion-container" id="accordion-container">
+ <accordion close-others="true" css="att-accordion--no-box">
+ <div ng-repeat="parent in sidebarModel.navItems">
+ <div ng-click="refreshOnlineUsers()" id="parent-item-{{parent.name.split(' ').join('-')}}"
+ class="parent-item"
+ ng-if="!parent.subMenu"
+ class="child-row"
+ ui-sref="{{parent.state}}" ui-sref-active="att-accordion-active">
+ <i id="icon-image-{{parent.name.split(' ').join('-')}}" ng-class="parent.imageSrc" class=\"pull-left\"></i>
+ &nbsp;&nbsp;{{parent.name}}
+ </div>
+
+ <accordion-group
+ id="accordion-group"
+ ng-if="parent.subMenu"
+ heading="{{parent.name}}"
+ image-source="{{parent.imageSrc}}" >
+ <div id="sub-item-{{child.name.split(' ').join('-')}}"
+ class="sub-item"
+ ng-repeat="child in parent.subMenu"
+ class="child-row"
+ ui-sref="{{child.state}}" ui-sref-active="att-accordion-active"
+ image-source="{{parent.imageSrc}}">
+ <i id="child-item-{{child.name.split(' ').join('-')}}" ng-class="child.imageSrc" class=\"pull-left\"></i>&nbsp;&nbsp;{{child.name}}
+ </div>
+ </accordion-group>
+
+ </div>
+ </accordion>
+
+ </div>
+ </div>
+</div>
diff --git a/ecomp-portal-FE/client/app/directives/multiple-select/multiple-select.directive.js b/ecomp-portal-FE/client/app/directives/multiple-select/multiple-select.directive.js
new file mode 100644
index 00000000..e8f6ed94
--- /dev/null
+++ b/ecomp-portal-FE/client/app/directives/multiple-select/multiple-select.directive.js
@@ -0,0 +1,111 @@
+/*-
+ * ================================================================================
+ * 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.
+ * ================================================================================
+ */
+
+angular.module('ecompApp')
+ .directive('multipleSelect', function ($window) {
+ return {
+ restrict: 'E',
+ templateUrl: 'app/directives/multiple-select/multiple-select.tpl.html',
+ scope: {
+ onChange: '&',
+ nameAttr: '@',
+ valueAttr: '@',
+ ngModel: '=',
+ placeholder: '@',
+ uniqueData: '@?',
+ onDropdownClose: '&?'
+ },
+ link: function(scope, elm, attrs){
+ scope.isExpanded = false;
+
+ scope.isDisabled = !scope.ngModel || !scope.ngModel.length;
+ scope.$watch('ngModel', function(newVal){
+ scope.isDisabled = !newVal || !newVal.length;
+ });
+
+
+ let startListening = () => {
+ console.log('listening on $window!');
+ angular.element($window).on('click', function () {
+ stopListening();
+ });
+
+ angular.element('multiple-select').on('click', function(e) {
+ if($(e.target).closest('multiple-select')[0].attributes['unique-data'].value === attrs.uniqueData){
+ console.log('ignored that..:', attrs.uniqueData);
+ e.stopPropagation();
+ }else{
+ console.log('shouldnt ignore, close expanded!:', attrs.uniqueData);
+ scope.isExpanded = false;
+ scope.$applyAsync();
+ }
+ });
+ };
+
+ let stopListening = function() {
+ if(scope.onDropdownClose){
+ scope.onDropdownClose();
+ }
+ scope.isExpanded = false;
+ scope.$applyAsync();
+ console.log('stop listening on $window and multiple-element!');
+ angular.element($window).off('click');
+ angular.element('multiple-select').off('click');
+ };
+
+ scope.showCheckboxes = function(){
+ scope.isExpanded = !scope.isExpanded;
+ if(scope.isExpanded){
+ startListening();
+ }else{
+ stopListening();
+ if(scope.onDropdownClose){
+ scope.onDropdownClose();
+ }
+ }
+ };
+
+ scope.onCheckboxClicked = function() {
+ console.log('checkbox clicked; unique data: ',attrs.uniqueData);
+ if(scope.onChange) {
+ scope.onChange();
+ }
+ }
+
+ scope.getTitle = function(){
+ var disp = "";
+ if(!scope.ngModel || !scope.ngModel.length) {
+ return disp;
+ }
+ scope.ngModel.forEach(function(item){
+ if(item[scope.valueAttr]){
+ disp+=item[scope.nameAttr] + ",";
+ }
+ });
+ if(disp!==""){
+ disp = disp.slice(0,disp.length-1);
+ }else{
+ disp = scope.placeholder;
+ }
+ return disp;
+ };
+ }
+ };
+ });
diff --git a/ecomp-portal-FE/client/app/directives/multiple-select/multiple-select.less b/ecomp-portal-FE/client/app/directives/multiple-select/multiple-select.less
new file mode 100644
index 00000000..6e54c8b6
--- /dev/null
+++ b/ecomp-portal-FE/client/app/directives/multiple-select/multiple-select.less
@@ -0,0 +1,81 @@
+/*-
+ * ================================================================================
+ * 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.
+ * ================================================================================
+ */
+ .multiple-select{
+ position: relative;
+ width: 100%;
+
+ .selectBox{
+ cursor: pointer;
+ position: relative;
+ border: 1px solid @o;
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ line-height: 30px;
+ height: 30px;
+ padding-left: 10px;
+ padding-right: 10px;
+
+ &.open::after{
+ content: '';
+ .arrow_up;
+ display: block;
+ position: absolute;
+ top: 12px;
+ right: 4px;
+ }
+ &.closed::after{
+ content: '';
+ .arrow_down;
+ display: block;
+ position: absolute;
+ top: 12px;
+ right: 4px;
+ }
+ &.disabled{
+ cursor: default;
+ background: #CCCCCC;
+ }
+
+ }
+
+ .checkboxes{
+ z-index: 99999;
+ padding-left: 8px;
+ padding-right: 8px;
+ position: absolute;
+ top: 30px;
+ width: 100%;
+ background: white;
+
+ display: block;
+ border: 1px #dadada solid;
+
+ label{
+ cursor: pointer;
+ display: block;
+ }
+ input{
+ cursor: pointer;
+ }
+
+
+ }
+} \ No newline at end of file
diff --git a/ecomp-portal-FE/client/app/directives/multiple-select/multiple-select.tpl.html b/ecomp-portal-FE/client/app/directives/multiple-select/multiple-select.tpl.html
new file mode 100644
index 00000000..e55e844c
--- /dev/null
+++ b/ecomp-portal-FE/client/app/directives/multiple-select/multiple-select.tpl.html
@@ -0,0 +1,38 @@
+<!--
+ ================================================================================
+ eCOMP Portal
+ ================================================================================
+ Copyright (C) 2017 AT&T Intellectual Property
+ ================================================================================
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ ================================================================================
+ -->
+ <div class="dropdown-container" style="height:30px;">
+ <div class="right_arrow_down" style="left:185px"></div>
+ <div class="multiple-select">
+ <div class="selectBox"
+ ng-click="isDisabled || showCheckboxes()"
+ title="{{getTitle()}}"
+ ng-bind="getTitle()"
+ ng-class="{open: isExpanded, closed: !isExpanded, disabled: isDisabled}"></div>
+
+ <div class="checkboxes" ng-show="isExpanded">
+ <div ng-repeat="item in ngModel">
+ <label>
+ <input type="checkbox" ng-model="item[valueAttr]" ng-change="onCheckboxClicked()">
+ {{item[nameAttr]}}
+ </label>
+ </div>
+ </div>
+ </div>
+</div>
diff --git a/ecomp-portal-FE/client/app/directives/right-click-menu/right-click-menu.directive.js b/ecomp-portal-FE/client/app/directives/right-click-menu/right-click-menu.directive.js
new file mode 100644
index 00000000..358cc56f
--- /dev/null
+++ b/ecomp-portal-FE/client/app/directives/right-click-menu/right-click-menu.directive.js
@@ -0,0 +1,38 @@
+/*-
+ * ================================================================================
+ * 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';
+angular.module('ecompApp').directive( "contextMenu", function($compile){
+ contextMenu = {};
+ contextMenu.restrict = "AE";
+ contextMenu.link = function( lScope, lElem, lAttr ){
+ lElem.on("contextmenu", function (e) {
+ e.preventDefault();
+ lElem.append( $compile( lScope[ lAttr.contextMenu ])(lScope) );
+ $("#contextmenu-node").css("left", e.clientX);
+ $("#contextmenu-node").css("top", e.clientY);
+ });
+ lElem.on("mouseleave", function(e){
+ console.log("Leaved the div");
+ if($("#contextmenu-node") )
+ $("#contextmenu-node").remove();
+ });
+ };
+ return contextMenu;
+});
diff --git a/ecomp-portal-FE/client/app/directives/right-click/ng-right-click-directive.js b/ecomp-portal-FE/client/app/directives/right-click/ng-right-click-directive.js
new file mode 100644
index 00000000..075ea3ac
--- /dev/null
+++ b/ecomp-portal-FE/client/app/directives/right-click/ng-right-click-directive.js
@@ -0,0 +1,32 @@
+/*-
+ * ================================================================================
+ * eCOMP Portal
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ================================================================================
+ */
+angular.module('ecompApp').
+ directive('ngRightClick', function($parse) {
+ return function(scope, element, attrs)
+ {
+ var fn = $parse(attrs.ngRightClick);
+ element.bind('contextmenu', function(event) {
+ scope.$apply(function() {
+ event.preventDefault();
+ fn(scope, {$event:event});
+ });
+ });
+ };
+ });
diff --git a/ecomp-portal-FE/client/app/directives/right-menu/right-menu.directive.js b/ecomp-portal-FE/client/app/directives/right-menu/right-menu.directive.js
new file mode 100644
index 00000000..b778ce7b
--- /dev/null
+++ b/ecomp-portal-FE/client/app/directives/right-menu/right-menu.directive.js
@@ -0,0 +1,140 @@
+/*-
+ * ================================================================================
+ * 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 1/28/16.
+ */
+(function () {
+ class RightMenu {
+ constructor($rootScope,$window,$log,userbarUpdateService) {
+ this.templateUrl = 'app/directives/right-menu/right-menu.tpl.html';
+ this.restrict = 'AE';
+ this.$rootScope = $rootScope;
+ this.userbarUpdateService = userbarUpdateService;
+ this.$window = $window;
+ this.$log = $log;
+ this.link = this._link.bind(this);
+ this.scope = {
+ userList :'='
+ }
+ }
+
+
+
+ _link(scope) {
+ let init = () => {
+ scope.isOpen = true;
+ scope.rightSideToggleBtn = 'Collapse';
+
+ scope.openInNewTab = (url) => {
+ if(url == "self") {
+ alert("Cannot chat with self!");
+ } else {
+ var win = window.open(url, '_blank');
+ setCookie(url.split("chat_id=")[1], 'source', 1);
+ //window.localStorage.setItem(url.split("chat_id=")[1],'source');
+ win.focus();
+ }
+ };
+
+ };
+
+ function setCookie(cname,cvalue,exdays) {
+ var d = new Date();
+ d.setTime(d.getTime() + (exdays*24*60*60*1000));
+ var expires = "expires=" + d.toGMTString();
+ document.cookie = cname + "=" + cvalue + ";" + expires + ";path=/";
+ }
+
+ function getCookie(cname) {
+ var name = cname + "=";
+ var decodedCookie = decodeURIComponent(document.cookie);
+ var ca = decodedCookie.split(';');
+ for(var i = 0; i < ca.length; i++) {
+ var c = ca[i];
+ while (c.charAt(0) == ' ') {
+ c = c.substring(1);
+ }
+ if (c.indexOf(name) == 0) {
+ return c.substring(name.length, c.length);
+ }
+ }
+ return "";
+ }
+
+
+
+ init();
+
+ /***Getting the list of the users***/
+ scope.toggleSidebar = () => {
+ scope.isOpen = !scope.isOpen;
+ if(scope.isOpen){
+ scope.rightSideToggleBtn = 'Collapse';
+ }else{
+ scope.rightSideToggleBtn = 'Expand';
+ }
+ };
+
+ scope.isBrowserInternetExplorer = false;
+ scope.browserName = bowser.name;
+
+ if (bowser.msie || bowser.msedge) {
+ scope.isBrowserInternetExplorer = true;
+ } else {
+ scope.isBrowserInternetExplorer = false;
+ }
+
+
+
+
+ scope.calculateUserBarHeight = () => {
+ var footerOff = $('#online-userbar').offset().top;
+ var headOff = $('#footer').offset().top;
+ var userbarHeight= parseInt($(".online-user-container").css('height'),10);
+ var defaultOffSet = 45;
+ // console.log(headOff - footerOff-defaultOffSet);
+ $(".online-user-container").css({
+ "height" : headOff - footerOff-defaultOffSet
+ });
+ };
+
+ let log = this.$log;
+
+ this.userbarUpdateService.getWidthThresholdRightMenu().then(function (res) {
+ if (res.status=="ERROR") {
+ log.error('userbarUpdateService: failed to get window width threshold for collapsing right menu; please make sure "window_width_threshold_right_menu" is specified in system.properties file.');
+ } else {
+ var rightMenuCollapseWidthThreshold = parseInt(res.response.windowWidth);
+ if ($(window).width()<rightMenuCollapseWidthThreshold) {
+ scope.toggleSidebar();
+ }
+ }
+ })['catch'](function (err) {
+ log.error('LeftMenu Controller:: getWidthThresholdLeftMenu() failed: ' + err);
+ });
+
+ angular.element(this.$window).bind('resize', function(){
+ scope.calculateUserBarHeight();
+ });
+ }
+
+ }
+ angular.module('ecompApp').directive('rightMenu', ($rootScope,$window,$log,userbarUpdateService) => new RightMenu($rootScope,$window,$log,userbarUpdateService));
+})();
diff --git a/ecomp-portal-FE/client/app/directives/right-menu/right-menu.less b/ecomp-portal-FE/client/app/directives/right-menu/right-menu.less
new file mode 100644
index 00000000..bc23b614
--- /dev/null
+++ b/ecomp-portal-FE/client/app/directives/right-menu/right-menu.less
@@ -0,0 +1,178 @@
+/*-
+ * ================================================================================
+ * 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 1/28/16.
+ */
+@sidebar-width: 200px;
+@transition-duration: 0.25s;
+@overlayer-opacity: 0.65;
+
+
+.close-button {
+ //width: @sidebar-width;
+ .a24r;
+ //.bg_u;
+ font-size: 3em;
+ line-height: 18px;
+ position: absolute;
+ cursor: pointer;
+ vertical-align: middle;
+ top: @second-level-top;
+ left: 0;
+ -webkit-font-smoothing: antialiased;
+ height: 53px;
+ z-index: 101;
+ //box-shadow: 0 4px 5px rgba(0, 0, 0, .2);
+
+}
+.ecomp-right-sidebar-container{
+ position: absolute;
+ display: block;
+ left: 0;
+ z-index: 100;
+ transition: left @transition-duration;
+ margin-top: -15px;
+
+ .ecomp-sidebar-main {
+ //background-color: ;
+ position: absolute;
+ margin-top: 65px;
+ width: @sidebar-width;
+ height: 100vh;
+ .bg_u;//white for 1610
+ //.bg_w; // gray for 1702
+ box-shadow: 0 4px 5px rgba(0, 0, 0, .2);
+
+ padding-right: 10px;
+ padding-left: 10px;
+
+ .accordion-container{
+ margin-top: 45px;
+ }
+ .att-accordion-font{
+ font-size: .875rem;
+ color: #666;
+ display: inline-block;
+ font-family: arial;
+
+ }
+
+ .att-accordion-active{
+ color: #199DDF !important;
+ }
+
+ .sub-item{
+ .att-accordion-font;
+ cursor: pointer;
+ height: 37px;
+ line-height: 37px;
+ padding-left: 20px;
+ padding-bottom: 10px;
+ vertical-align: middle;
+ width: 100%;
+ }
+ .sub-item:hover{
+ .att-accordion-active;
+ }
+
+ .parent-item{
+ .att-accordion-font;
+ border-bottom: 1px solid #bbb;
+ cursor: pointer;
+ height: 37px;
+ line-height: 37px;
+ padding-bottom: 10px;
+ vertical-align: middle;
+ width: 100%;
+ }
+ .parent-item:hover{
+ .att-accordion-active;
+ }
+
+ }
+}
+
+.open-sidebar {
+ right: 0;
+ transition: right .25s ease-in-out;
+ -moz-transition: right .25s ease-in-out;
+ -webkit-transition: right .25s ease-in-out;
+}
+
+.close-sidebar {
+ right: -@sidebar-width;
+ transition: right .25s ease-in-out;
+ -moz-transition: right .25s ease-in-out;
+ -webkit-transition: right .25s ease-in-out;
+}
+
+.content-overlayed {
+ position: fixed;
+ top: 110px;
+ right: 0;
+ bottom: 0;
+ left: 0;
+ background: none repeat scroll 0 0 rgb(242, 242, 242);
+ z-index: 9999;
+}
+.fade-animation{
+ opacity: @overlayer-opacity;
+ transition: opacity @transition-duration ease-in-out;
+}
+.fade-animation.ng-hide {
+ opacity:0;
+ transition: opacity @transition-duration ease-in-out;
+}
+
+.activeUserIcon {
+ transition: all .2s ease-in-out;
+ display: block;
+ margin-left: auto; margin-right: auto; height:55px; width:55px; border-radius: 50%;
+
+}
+.activeUserIcon:hover { transform: scale(1.5); }
+
+.ecomp-right-sidebar-toggle{
+ position: absolute;
+ top: 400px;
+ right: 35px;
+}
+
+.open-sidebar-toggle {
+ // right: 0;
+ transition: right .25s ease-in-out;
+ -moz-transition: right .25s ease-in-out;
+ -webkit-transition: right .25s ease-in-out;
+}
+
+.close-sidebar-toggle {
+ right: -36px;
+ transition: right .25s ease-in-out;
+ -moz-transition: right .25s ease-in-out;
+ -webkit-transition: right .25s ease-in-out;
+}
+
+.ecomp-right-sidebar-title{
+ font-family: arial;
+ font-size: 14px;
+ color: #ef6f00;
+ margin-bottom:20px;
+ text-align: center;
+} \ No newline at end of file
diff --git a/ecomp-portal-FE/client/app/directives/right-menu/right-menu.tpl.html b/ecomp-portal-FE/client/app/directives/right-menu/right-menu.tpl.html
new file mode 100644
index 00000000..39eb7087
--- /dev/null
+++ b/ecomp-portal-FE/client/app/directives/right-menu/right-menu.tpl.html
@@ -0,0 +1,40 @@
+<!--
+ ================================================================================
+ eCOMP Portal
+ ================================================================================
+ Copyright (C) 2017 AT&T Intellectual Property
+ ================================================================================
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ ================================================================================
+ -->
+<div id="ecomp-right-sidebar-container" class="ecomp-sidebar-container" ng-class="isOpen ? 'open-sidebar': 'close-sidebar'">
+ <div id="online-userbar" class="ecomp-sidebar-main" style="right: 0px; width:75px; padding:0px;" >
+ <div class="online-user-container" id="online-user-container" style="margin-top:45px; overflow-y:auto; overflow-x:hidden">
+ <div class="ecomp-right-sidebar-title">Online Users</div>
+ <div ng-repeat="user in userList">
+ <div class="child-row" style="height:85px;" ui-sref-active="att-accordion-active">
+ <div>
+ <a href="javascript:void(0)" ng-click="openInNewTab(user.linkQ)" ><img class="activeUserIcon" ng-src="assets/images/photo.png" alt="User Link" ></a>
+ <div style="font-family: Arial; font-size:10px; text-align: center;" >{{user.userId}}</div>
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+</div>
+<div class="ecomp-right-sidebar-toggle" ng-class="isOpen ? 'open-sidebar-toggle': 'close-sidebar-toggle'">
+ <a href="javascript:void(0)" ng-click="toggleSidebar()" style="transform: rotate(-90deg); position:relative; z-index:5" att-button btn-type="primary" size="small" att-accessibility-click="13,32">
+ <span class="ion-chevron-down" ng-show="isOpen"></span>
+ <span class="ion-chevron-up" ng-hide="isOpen"><span style="font-family: arial">Users</span></span>
+ </a>
+</div>
diff --git a/ecomp-portal-FE/client/app/directives/scroll-top/scroll-top.directive.js b/ecomp-portal-FE/client/app/directives/scroll-top/scroll-top.directive.js
new file mode 100644
index 00000000..148660b5
--- /dev/null
+++ b/ecomp-portal-FE/client/app/directives/scroll-top/scroll-top.directive.js
@@ -0,0 +1,35 @@
+/*-
+ * ================================================================================
+ * 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.
+ * ================================================================================
+ */
+
+angular.module('ecompApp')
+ .directive('scrollTop', function () {
+ return {
+ restrict: 'A',
+ scope: {api: '=scrollTop'},
+ link: function (scope, element) {
+ scope.api = scope.api || {};
+ scope.api.scrollTop = function() {
+ element.animate({
+ scrollTop : 0
+ }, 500);
+ };
+ }
+ };
+ });
diff --git a/ecomp-portal-FE/client/app/directives/search-users/search-users.controller.js b/ecomp-portal-FE/client/app/directives/search-users/search-users.controller.js
new file mode 100644
index 00000000..649b3ab2
--- /dev/null
+++ b/ecomp-portal-FE/client/app/directives/search-users/search-users.controller.js
@@ -0,0 +1,161 @@
+/*-
+ * ================================================================================
+ * 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 SearchUsersCtrl {
+
+ constructor($log, usersService,adminsService, $scope,confirmBoxService) {
+
+ $scope.UserSearchsIsNull=false;
+ $scope.userExist = false;
+ this.scrollApi = {};//scrollTop directive
+
+ this.showAddUser = false;
+ this.showSearch = true;
+ this.newUser ={
+ firstName:'',
+ lastName:'',
+ emailAddress:'',
+
+ middleName:'',
+ loginId:'',
+ loginPwd:'',
+ loginPwdCheck:''
+ };
+
+ let activeRequests = [];
+ let clearReq = (req) => {
+ activeRequests.splice(activeRequests.indexOf(req), 1);
+ };
+
+ this.showAddUserSection = () => {
+ this.showAddUser = true;
+ this.showSearch = false;
+ }
+
+ this.addNewUserFun = () => {
+ if (this.newUser.loginId =='' || this.newUser.loginPwd == '' || this.newUser.firstName == '' || this.newUser.lastName =='' || this.newUser.emailAddress ==''||this.newUser.loginPwd ==''){
+ var warningMsg = "Please enter a value for all fields marked with *.";
+ confirmBoxService.showInformation(warningMsg).then(isConfirmed => {return;});
+ return;
+ } else if (this.newUser.loginPwd != this.newUser.loginPwdCheck) {
+ 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.newUser.loginPwd);
+ if (warningMsg != null) {
+ confirmBoxService.showInformation(warningMsg).then(isConfirmed => {return;});
+ return;
+ }
+ } // password
+
+ adminsService.addNewUser(this.newUser,'Yes').then(res=> {
+
+ if(res.message == 'Record already exist'){
+
+ this.showAddUser = true;
+ this.showSearch = false;
+ $scope.userExist = true;
+
+ }else{
+
+ $scope.userExist = false;
+ this.selectedUser = this.newUser;
+ this.selectedUser.orgUserId = this.newUser.loginId;
+ this.searchUsersResults = [];
+ this.searchUsersResults.push(this.newUser);
+ this.showAddUser = false;
+ this.showSearch = true;
+ this.newUser ={
+ firstName:'',
+ lastName:'',
+ emailAdress:'',
+ middleName:'',
+ loginId:'',
+ loginPwd:'',
+ loginPwdCheck:''
+ };
+ this.searchUserString ='';
+ $scope.UserSearchsIsNull = false;
+ }
+
+
+ }).catch(err=> {
+ $log.error('adminsService: addNewUser error:: ', err);
+ // $scope.errMsg=err;
+ confirmBoxService.showInformation('Add New User failed: ' + err);
+
+ }).finally(() => {
+ //this.isLoadingTable = false;
+
+ });
+ }
+
+ this.searchUsers = () => {
+ this.isLoading = true;
+ if(this.searchUsersInProgress){
+ return;
+ }
+ this.selectedUser = null;
+ this.searchUsersInProgress = true;
+ this.searchUsersResults = null;
+
+ let searchUsersReq = usersService.searchUsers(this.searchUserString);
+ activeRequests.push(searchUsersReq);
+ searchUsersReq.promise().then(usersList => {
+ $log.debug('searchUsers found the following users: ', JSON.stringify(usersList));
+ this.searchUsersResults = usersList;
+ $scope.UserSearchsIsNull=false;
+ }).catch(err => {
+ $log.error('SearchUsersCtrl.searchUsers: ' + err);
+ $scope.UserSearchsIsNull=true;
+ }).finally(() => {
+ this.scrollApi.scrollTop();
+ this.searchUsersInProgress = false;
+ clearReq(searchUsersReq);
+ this.isLoading = false;
+ });
+ };
+
+ let init = () => {
+ this.isLoading = false;
+ this.searchUsersInProgress = false;
+ };
+
+ this.setSelectedUser = user => {
+ this.selectedUser = user;
+ };
+
+ init();
+
+ $scope.$on('$destroy', () => {
+ activeRequests.forEach(req => {
+ req.cancel();
+ });
+ });
+ }
+ }
+ SearchUsersCtrl.$inject = ['$log', 'usersService','adminsService', '$scope','confirmBoxService'];
+ angular.module('ecompApp').controller('SearchUsersCtrl', SearchUsersCtrl);
+})();
diff --git a/ecomp-portal-FE/client/app/directives/search-users/search-users.controller.spec.js b/ecomp-portal-FE/client/app/directives/search-users/search-users.controller.spec.js
new file mode 100644
index 00000000..96f5b0df
--- /dev/null
+++ b/ecomp-portal-FE/client/app/directives/search-users/search-users.controller.spec.js
@@ -0,0 +1,176 @@
+/*-
+ * ================================================================================
+ * 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';
+//
+//describe('Controller: NewAdminCtrl ', () => {
+// beforeEach(module('ecompApp'));
+//
+// //destroy $http default cache before starting to prevent the error 'default cache already exists'
+// beforeEach(inject((_CacheFactory_)=> {
+// _CacheFactory_.destroyAll();
+// }));
+//
+//
+// let newCtrl, $controller, $q, $rootScope, $log;
+//
+// beforeEach(inject((_$controller_, _$q_, _$rootScope_, _$log_)=> {
+// [$controller, $q, $rootScope, $log] = [_$controller_, _$q_, _$rootScope_, _$log_];
+// }));
+//
+// let deferredUsersList, deferredAdminAppsRoles, deferredUpdateRolesRes;
+// let usersServiceMock, adminsServiceMock;
+// beforeEach(()=> {
+// [deferredUsersList, deferredAdminAppsRoles, deferredUpdateRolesRes] = [$q.defer(), $q.defer(), $q.defer()];
+//
+// //usersServiceMock = jasmine.createSpyObj('usersServiceMock', ['searchUsers']);
+// usersServiceMock = {
+// searchUsers: () => {
+// var promise = () => {return deferredUsersList.promise};
+// var cancel = jasmine.createSpy();
+// return {
+// promise: promise,
+// cancel: cancel
+// }
+// }
+// };
+//
+// adminsServiceMock = jasmine.createSpyObj('adminsServiceMock', ['getAdminAppsRoles', 'updateAdminAppsRoles']);
+//
+// //usersServiceMock.searchUsers.and.returnValue(deferredUsersList.promise);
+// adminsServiceMock.getAdminAppsRoles.and.returnValue(deferredAdminAppsRoles.promise);
+// adminsServiceMock.updateAdminAppsRoles.and.returnValue(deferredUpdateRolesRes.promise);
+//
+// newCtrl = $controller('NewAdminModalCtrl', {
+// $log: $log,
+// usersService: usersServiceMock,
+// adminsService: adminsServiceMock,
+// $scope: $rootScope
+// });
+// });
+//
+// it('should init default values when loading the controller', ()=> {
+// //expect(newCtrl.searchUsersInProgress).toBe(false);
+// expect(newCtrl.dialogState).toBe(1);
+// expect(newCtrl.selectedUser).toBe(null);
+// });
+//
+// it('should populate retrieved users when search users service returns a list ', ()=> {
+// //spyOn(usersServiceMock, 'searchUsers');
+// let usersListRes = [{user: 1}, {user: 2}];
+// newCtrl.searchUserString = 'some user name';
+// deferredUsersList.resolve(usersListRes);
+// newCtrl.searchUsers();
+// $rootScope.$apply();
+//
+// //expect(usersServiceMock.searchUsers).toHaveBeenCalledWith(newCtrl.searchUserString);
+// expect(newCtrl.searchUsersResults).toEqual(usersListRes);
+// expect(newCtrl.searchUsersInProgress).toBe(false);
+// });
+//
+// it('should log the error when search users fails', ()=> {
+// spyOn($log, 'error');
+// deferredUsersList.reject('oh snap!');
+// newCtrl.searchUsers();
+// $rootScope.$apply();
+// expect($log.error).toHaveBeenCalled();
+// });
+//
+// it('should populate admin apps roles and move to the next screen when adminsService.getAdminAppsRoles succeeded', ()=> {
+// let userApps = {appsRoles: [{id: 1, isAdmin: false}, {id: 2, isAdmin: true}]};
+// deferredAdminAppsRoles.resolve(userApps);
+//
+// newCtrl.searchUsersInProgress = false;
+// newCtrl.selectedUser = {userId: 'userId'};
+//
+// newCtrl.getAdminAppsRoles();
+// $rootScope.$apply();
+//
+// expect(adminsServiceMock.getAdminAppsRoles).toHaveBeenCalledWith(newCtrl.selectedUser.userId);
+// expect(newCtrl.adminAppsRoles).toEqual(userApps.appsRoles);
+// expect(newCtrl.dialogState).toBe(2);
+// });
+//
+// it('should log the error when adminsService.getAdminAppsRoles fails', ()=> {
+// spyOn($log, 'error');
+// deferredAdminAppsRoles.reject('some error');
+//
+// newCtrl.searchUsersInProgress = false;
+// newCtrl.selectedUser = {userId: 'userId'};
+//
+// newCtrl.getAdminAppsRoles();
+// $rootScope.$apply();
+//
+// expect($log.error).toHaveBeenCalled();
+// });
+// it('should log the error when trying to getAdminAppsRoles without selecting user ', ()=> {
+// spyOn($log, 'error');
+//
+// newCtrl.searchUsersInProgress = false;
+// newCtrl.selectedUser = null;
+//
+// newCtrl.getAdminAppsRoles();
+// $rootScope.$apply();
+//
+// expect($log.error).toHaveBeenCalled();
+// });
+// //it('should setSelectedUser when choosing user', ()=> {
+// //
+// //});
+// //it('should set isAdmin as false when removing app from the administrated apps list', ()=> {
+// //});
+// it('should set isAdmin as true when adding app via the dropdown menu', ()=> {
+// newCtrl.adminAppsRoles = [{id: 1, isAdmin: false},{id: 2, isAdmin: true}];
+// //simulate UI change
+// $rootScope.$apply('newAdmin.selectedNewApp = null');
+// $rootScope.$apply('newAdmin.selectedNewApp = {id: 1, isAdmin: true}');
+//
+// expect(newCtrl.adminAppsRoles[0].isAdmin).toBe(true);
+// expect(newCtrl.selectedNewApp).toBe(null);
+// });
+//
+// it('should close the modal when updating apps roles succeeded', ()=> {
+// $rootScope.closeThisDialog = () => {};
+// spyOn($rootScope,'closeThisDialog');
+//
+// newCtrl.selectedUser = {userId: 'userId'};
+// newCtrl.adminAppsRoles = [{id: 1}];
+//
+// deferredUpdateRolesRes.resolve();
+// newCtrl.updateAdminAppsRoles();
+// $rootScope.$apply();
+//
+// expect(adminsServiceMock.updateAdminAppsRoles).toHaveBeenCalledWith({userId: newCtrl.selectedUser.userId, appsRoles: newCtrl.adminAppsRoles});
+// expect($rootScope.closeThisDialog).toHaveBeenCalled();
+// });
+// it('should log the error when updating apps roles fails', ()=> {
+// newCtrl.selectedUser = {userId: 'userId'};
+// newCtrl.adminAppsRoles = [{id: 1}];
+//
+// spyOn($log,'error');
+// deferredUpdateRolesRes.reject();
+// newCtrl.updateAdminAppsRoles();
+// $rootScope.$apply();
+// expect($log.error).toHaveBeenCalled();
+// });
+// //it('should display the add admin dropdown when clicking the add button', ()=> {
+// //});
+//
+//});
diff --git a/ecomp-portal-FE/client/app/directives/search-users/search-users.directive.js b/ecomp-portal-FE/client/app/directives/search-users/search-users.directive.js
new file mode 100644
index 00000000..4e5809f9
--- /dev/null
+++ b/ecomp-portal-FE/client/app/directives/search-users/search-users.directive.js
@@ -0,0 +1,34 @@
+/*-
+ * ================================================================================
+ * 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.
+ * ================================================================================
+ */
+
+angular.module('ecompApp')
+ .directive('searchUsers', function () {
+ return {
+ restrict: 'E',
+ templateUrl: 'app/directives/search-users/search-users.tpl.html',
+ controller: 'SearchUsersCtrl',
+ controllerAs: 'searchUsers',
+ bindToController: true,
+ scope: {
+ selectedUser: '=',
+ searchTitle: '@'
+ }
+ };
+ });
diff --git a/ecomp-portal-FE/client/app/directives/search-users/search-users.less b/ecomp-portal-FE/client/app/directives/search-users/search-users.less
new file mode 100644
index 00000000..9c6de2b4
--- /dev/null
+++ b/ecomp-portal-FE/client/app/directives/search-users/search-users.less
@@ -0,0 +1,154 @@
+/*-
+ * ================================================================================
+ * 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.
+ * ================================================================================
+ */
+ .search-users-directive{
+ .title {
+ .n18r;
+ border-bottom: @a 3px solid;
+
+ }
+
+ .add-user-section{
+ margin-top:0px;
+ margin-left:10px;
+ }
+
+ .input-text-new-user {
+ font-style: italic;
+ padding: 7px 10px;
+ width: 200px !important;
+ display: inline-block;
+ position: relative;
+ margin-bottom: 10px;
+ border-radius: 6px;
+ border: 1px solid #d8d8d8;
+ height: 32px;
+ border-color: slategrey !important;
+ }
+
+ .input-new-user-div{
+
+ margin-left:10px;
+ }
+
+ .add-user-button {
+ cursor: pointer;
+ float:right;
+ width: 120px;
+
+ margin-left : 5px;
+
+ .btn-blue;
+
+ line-height: 32px;
+ height: 29px;
+ text-align: center;
+ vertical-align: middle;
+ line-height: 28px;
+
+ &::before {
+ .ico_add_user;
+ content: '\f211';
+ font-family: "Ionicons";
+ vertical-align: middle;
+ display: inline-block;
+ margin-right: 8px;
+ line-height: 16px;
+ }
+ }
+
+ .main {
+ margin: 16px;
+ .search-instructions {
+ .n14r;
+ margin-bottom: 8px;
+ }
+ .search {
+ .input-field {
+ display: inline-block;
+ width: 250px;
+ height: 30px;
+ }
+ .search-button {
+ .btn-blue;
+ width: 90px;
+ display: inline-block;
+ float: right;
+ }
+ }
+
+ .search-results {
+ margin-top: 10px;
+ .results-title {
+ .n14r;
+ margin-bottom: 8px;
+ }
+
+ .results-container {
+ height: 208px;
+ overflow-y: auto;
+ .user {
+ padding-left: 10px;
+ padding-top: 6px;
+ height: 48px;
+
+ border-top: 1px solid @p;
+ border-right: 1px solid @p;
+ border-left: 1px solid @p;
+
+ &:last-child {
+ border-bottom: 1px solid @p;
+ }
+
+ cursor: pointer;
+ &:hover {
+ background-color: @v;
+ }
+
+ &.selected {
+ background-color: @v;
+ }
+
+ .main-name {
+ .n14r;
+
+ }
+ .sub-job-title {
+ .p13r;
+
+ }
+ }
+
+ }
+
+ }
+ .error-text {
+ margin-top: 25px;
+ font-weight: 400;
+ font-size: 16px;
+ text-align: left;
+ color: @err;
+ }
+
+ .no-user-found {
+ margin-top: 16px;
+ .n14r;
+ }
+ }
+} \ No newline at end of file
diff --git a/ecomp-portal-FE/client/app/directives/search-users/search-users.tpl.html b/ecomp-portal-FE/client/app/directives/search-users/search-users.tpl.html
new file mode 100644
index 00000000..6c275693
--- /dev/null
+++ b/ecomp-portal-FE/client/app/directives/search-users/search-users.tpl.html
@@ -0,0 +1,144 @@
+<!--
+ ================================================================================
+ eCOMP Portal
+ ================================================================================
+ Copyright (C) 2017 AT&T Intellectual Property
+ ================================================================================
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ ================================================================================
+ -->
+<div class="search-users-directive">
+ <form name="searchUsersForm" novalidate>
+ <div class="title" ng-bind="searchUsers.searchTitle"></div>
+ <div class="main">
+ <div ng-if="searchUsers.showSearch">
+ <div class="search-instructions">Enter first name, last name or User ID</div>
+ <div class="search">
+ <input id="input-user-search"
+ class="input-field"
+ autocomplete="off"
+ type="text"
+ name="searchString"
+ placeholder="Search"
+ ng-model="searchUsers.searchUserString"
+ ng-keyup="$event.keyCode===13 && searchUsersForm.searchString.$valid && searchUsers.searchUsers()"
+ pattern="[a-zA-Z0-9-'\s]{1,}"
+ maxlength="80"
+ required="true" auto-focus tabindex="0"/>
+
+ <div id="Create-New-User-button" class="add-user-button" ng-click="searchUsers.showAddUserSection()">New User</div>
+ <div id="button-search-users"
+ class="search-button"
+ tabindex="2"
+ ng-class="{disabled: searchUsersForm.searchString.$invalid || searchUsers.searchUsersInProgress}"
+ ng-click="searchUsersForm.searchString.$valid && searchUsers.searchUsers()">
+ Search
+ </div>
+
+ </div>
+
+ <span class="ecomp-spinner" ng-show="searchUsers.isLoading"></span>
+ <div ng-show="UserSearchsIsNull===false">
+ <div class="search-results"
+ ng-show="!searchUsers.isLoading
+ && searchUsers.searchUsersResults
+ && searchUsers.searchUsersResults.length">
+ <div id="search-results" ng-show="UserSearchsIsNull===false"
+ class="results-title"
+ ng-bind="'Showing ' + searchUsers.searchUsersResults.length + ' results'"></div>
+ <div class="results-container" scroll-top="searchUsers.scrollApi">
+ <div id="search-result-{{$index}}"
+ class="user"
+ ng-repeat="user in (searchUsers.searchUsersResults | orderBy:['firstName','lastName','orgUserId']) | limitTo: 100 track by $index"
+ ng-click="searchUsers.setSelectedUser(user)"
+ ng-class="{selected: user.orgUserId === searchUsers.selectedUser.orgUserId}">
+ <div id="main-name-{{$index}}" class="main-name">
+ <span id="result-first-name-{{$index}}" ng-bind="::user.firstName"></span>
+ <span id="result-last-name-{{$index}}" ng-bind="::user.lastName"></span>
+ <span id="result-uuid-{{$index}}" ng-bind="::user.orgUserId"></span></div>
+ <div id="job-title-{{$index}}" class="sub-job-title" ng-bind="::user.jobTitle"></div>
+ <br/>
+ </div>
+ </div>
+ </div>
+ </div>
+
+ <div class="error-text"
+ id="user-search-error-403"
+ ng-show="UserSearchsIsNull===true">
+ No match found.
+ </div>
+
+ <div id="no-user-found"
+ class="no-user-found"
+ ng-show="searchUsers.searchUsersResults && searchUsers.searchUsersResults.length===0 && !searchUsers.searchUsersInProgress">
+ No users found
+ </div>
+ </div>
+
+
+ <div id="addWidget" class="add-user-section" ng-if="searchUsers.showAddUser">
+ <div>
+ <div class="input-new-user-div" >
+ <div class="">*First Name</div>
+ <input class="input-text-new-user" type="text" ng-model="searchUsers.newUser.firstName"/>
+ </div>
+ <div class="input-new-user-div" >
+ <div class="">Middle Name</div>
+ <input class="input-text-new-user" type="text" ng-model="searchUsers.newUser.middleName"/>
+ </div>
+ <div class="input-new-user-div" >
+ <div class="">*Last Name</div>
+ <input class="input-text-new-user" type="text" ng-model="searchUsers.newUser.lastName"/>
+ </div>
+ <div class="input-new-user-div" >
+ <div class="">*Email Address ID</div>
+ <input class="input-text-new-user" type="text" ng-model="searchUsers.newUser.emailAddress"/>
+ </div>
+ <div class="input-new-user-div" >
+ <div class="">*Login ID</div>
+ <input class="input-text-new-user" type="text" ng-model="searchUsers.newUser.loginId"/>
+ </div>
+ <div class="input-new-user-div" >
+ <div class="">*Login Password</div>
+ <input class="input-text-new-user" type="password" ng-model="searchUsers.newUser.loginPwd"/>
+ </div>
+ <div class="input-new-user-div" >
+ <div class="">*Confirm Login Password</div>
+ <input class="input-text-new-user" type="password" ng-model="searchUsers.newUser.loginPwdCheck"/>
+ </div>
+ <div ng-show="searchUsers.newUser.loginPwdCheck.length>=searchUsers.newUser.loginPwd.length&&searchUsers.newUser.loginPwdCheck.length>0&&searchUsers.newUser.loginPwd!=searchUsers.newUser.loginPwdCheck"
+ style="color: #cf2a2a; font-size: 12px;">
+ <small
+ style="position: absolute; margin-top: -6px;">The passwords do not match. Try again.
+ </small>
+ </div>
+ <div ng-show="userExist==true"
+ style="color: #cf2a2a; font-size: 12px;">
+ <small
+ style="position: absolute; margin-top: -6px;">User with same loginId already exists. Try again.
+ </small>
+ </div>
+ </div>
+ <div style="height:50px;">
+ <a style="margin-right:10px;margin-top:20px;margin-bottom:5px" att-button btn-type="primary" class="button button--primary" size="small" ng-click="searchUsers.addNewUserFun()">Add New User</a>
+ </div>
+ </div>
+
+
+ </div>
+
+ </div>
+
+ </form>
+</div>