diff options
Diffstat (limited to 'catalog-ui/app/scripts/view-models/admin-dashboard')
13 files changed, 1235 insertions, 0 deletions
diff --git a/catalog-ui/app/scripts/view-models/admin-dashboard/add-category-modal/add-category-modal-view-model.ts b/catalog-ui/app/scripts/view-models/admin-dashboard/add-category-modal/add-category-modal-view-model.ts new file mode 100644 index 0000000000..93c1dac174 --- /dev/null +++ b/catalog-ui/app/scripts/view-models/admin-dashboard/add-category-modal/add-category-modal-view-model.ts @@ -0,0 +1,94 @@ +/*- + * ============LICENSE_START======================================================= + * SDC + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * 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. + * ============LICENSE_END========================================================= + */ +/// <reference path="../../../references"/> +module Sdc.ViewModels { + 'use strict'; + + interface IAddCategoryModalViewModelScope extends ng.IScope { + category:Sdc.Services.ICategoryResource; + modelType:string; + footerButtons: Array<any>; + forms:any; + + save():void; + close():void; + } + + export class AddCategoryModalViewModel { + + static '$inject' = [ + '$scope', + 'Sdc.Services.CategoryResourceService', + '$modalInstance', + 'parentCategory', + 'type' + ]; + + constructor( + private $scope:IAddCategoryModalViewModelScope, + private categoryResourceService:Sdc.Services.ICategoryResourceClass, + private $modalInstance:ng.ui.bootstrap.IModalServiceInstance, + private parentCategory:Sdc.Services.ICategoryResource, + private type:string + ){ + this.initScope(); + } + + private initScope = ():void => { + this.$scope.forms = {}; + this.$scope.modelType = this.parentCategory ? 'sub category' : 'category'; + this.$scope.category = new this.categoryResourceService(); + + this.$scope.close = ():void => { + this.$modalInstance.dismiss(); + }; + + this.$scope.save = ():void => { + + let onOk = (newCategory :Sdc.Services.ICategoryResource):void => { + this.$modalInstance.close(newCategory); + }; + + let onCancel = ():void => { + //error + }; + + if(!this.parentCategory) { + this.$scope.category.$save({types: this.type+"s"}, onOk, onCancel); + }else{ + this.$scope.category.$saveSubCategory({types: this.type+"s", categoryId: this.parentCategory.uniqueId}, onOk, onCancel); + } + + }; + + this.$scope.footerButtons = [ + {'name': 'OK', 'css': 'blue', 'callback': this.$scope.save, 'disabled': true}, + {'name': 'Cancel', 'css': 'grey', 'callback': this.$scope.close} + ]; + + this.$scope.$watch("forms.editForm.$invalid", (newVal, oldVal) => { + this.$scope.footerButtons[0].disabled = this.$scope.forms.editForm.$invalid; + }); + + } + + + } +} diff --git a/catalog-ui/app/scripts/view-models/admin-dashboard/add-category-modal/add-category-modal-view.html b/catalog-ui/app/scripts/view-models/admin-dashboard/add-category-modal/add-category-modal-view.html new file mode 100644 index 0000000000..5718982661 --- /dev/null +++ b/catalog-ui/app/scripts/view-models/admin-dashboard/add-category-modal/add-category-modal-view.html @@ -0,0 +1,41 @@ +<sdc-modal modal="modalInstance" + type="classic" + class="i-sdc-admin-add-category-modal modal-type-confirmation" + header-translate="CREATE_CATEGORY_MODAL_HEADER" + buttons="footerButtons" + header-translate-values="{'modelType': '{{modelType}}' }" + show-close-button="true" + hide-background="false" +> + + <form novalidate class="w-sdc-form" name="forms.editForm"> + + <div class="w-sdc-form-column"> + <div class="i-sdc-form-item" + data-ng-class="{error:(editForm.categoryName.$dirty && editForm.categoryName.$invalid)}"> + <label class="i-sdc-form-label required" translate="CREATE_CATEGORY_MODAL_CATEGORY_NAME" + translate-values="{'modelType': '{{modelType}}' }"></label> + <input class="i-sdc-form-input" + data-ng-model="category.name" + data-ng-model-options="{ debounce: 200 }" + type="text" + name="categoryName" + required="required" + data-ng-minlength="4" + data-ng-pattern="namePattern" + maxlength="25" + autofocus /> + + <div class="input-error" data-ng-show="editForm.categoryName.$dirty && editForm.categoryName.$invalid"> + <span ng-show="editForm.categoryName.$error.required" translate="CREATE_CATEGORY_MODAL_REQUIRED" translate-values="{'modelType': '{{modelType}}' }"></span> + <span ng-show="editForm.categoryName.$error.minlength" translate="CREATE_CATEGORY_MODAL_MINLENGTH" translate-values="{'minlength': '4', 'modelType': '{{modelType}}' }"></span> + <span ng-show="editForm.categoryName.$error.pattern" translate="CREATE_CATEGORY_MODAL_PATTERN" translate-values="{'modelType': '{{modelType}}' }"></span> + </div> + + </div> + + </div> + + </form> + +</sdc-modal> diff --git a/catalog-ui/app/scripts/view-models/admin-dashboard/add-category-modal/add-category-modal-view.less b/catalog-ui/app/scripts/view-models/admin-dashboard/add-category-modal/add-category-modal-view.less new file mode 100644 index 0000000000..39d84aab23 --- /dev/null +++ b/catalog-ui/app/scripts/view-models/admin-dashboard/add-category-modal/add-category-modal-view.less @@ -0,0 +1,3 @@ +.i-sdc-admin-add-category-modal { + +} diff --git a/catalog-ui/app/scripts/view-models/admin-dashboard/admin-dashboard-view-model.ts b/catalog-ui/app/scripts/view-models/admin-dashboard/admin-dashboard-view-model.ts new file mode 100644 index 0000000000..d7cbbcc68d --- /dev/null +++ b/catalog-ui/app/scripts/view-models/admin-dashboard/admin-dashboard-view-model.ts @@ -0,0 +1,82 @@ +/*- + * ============LICENSE_START======================================================= + * SDC + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * 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. + * ============LICENSE_END========================================================= + */ +/// <reference path="../../references"/> +module Sdc.ViewModels { + + 'use strict'; + + interface IAdminDashboardViewModelScope extends ng.IScope { + version:string; + sdcConfig:Models.IAppConfigurtaion; + isLoading: boolean; + currentTab: string; + templateUrl:string; + monitorUrl:string; + moveToTab(tab:string):void; + isSelected(tab:string):boolean; + } + + + export class AdminDashboardViewModel { + static '$inject' = [ + '$scope', + 'Sdc.Services.CacheService', + 'sdcConfig' + ]; + + constructor(private $scope:IAdminDashboardViewModelScope, + private cacheService:Services.CacheService, + private sdcConfig:Models.IAppConfigurtaion) { + + this.initScope(); + } + + + private initScope = ():void => { + + this.$scope.version = this.cacheService.get('version'); + this.$scope.sdcConfig = this.sdcConfig; + this.$scope.monitorUrl = this.$scope.sdcConfig.api.kibana; + this.$scope.isSelected=(tab:string):boolean => { + return tab===this.$scope.currentTab; + } + + this.$scope.moveToTab=(tab:string):void => { + if (tab===this.$scope.currentTab){ + return; + } + else if(tab === 'USER_MANAGEMENT'){ + this.$scope.templateUrl = '/app/scripts/view-models/admin-dashboard/user-management/user-management-view.html'; + } + else if(tab ==='CATEGORY_MANAGEMENT'){ + this.$scope.templateUrl = '/app/scripts/view-models/admin-dashboard/category-management/category-management-view.html'; + } + /* else if(tab ==='ECOMP'){ + this.$scope.templateUrl = '/app/scripts/view-models/admin-dashboard/ecomp/ecomp-view.html'; + }*/ + this.$scope.currentTab = tab; + }; + + this.$scope.moveToTab('USER_MANAGEMENT'); + + + } + } +} diff --git a/catalog-ui/app/scripts/view-models/admin-dashboard/admin-dashboard-view.html b/catalog-ui/app/scripts/view-models/admin-dashboard/admin-dashboard-view.html new file mode 100644 index 0000000000..063525a4bf --- /dev/null +++ b/catalog-ui/app/scripts/view-models/admin-dashboard/admin-dashboard-view.html @@ -0,0 +1,24 @@ +<div class="sdc-admin-container"> + + <!--<ecomp-header menu-data="menuItems" version="{{version}}" clickable-logo="false"></ecomp-header>--> + + <nav class="sdc-admin-top-bar-menu"> + <button class="sdc-admin-top-bar-menu-tab" data-tests-id="usermanagmenttab" + data-ng-class="{'selected': isSelected('USER_MANAGEMENT')}" + data-ng-click="moveToTab('USER_MANAGEMENT')" + translate="USER_MANAGEMENT"> + </button> + <button class="sdc-admin-top-bar-menu-tab" data-tests-id="categorymanagmenttab" + data-ng-class="{'selected': isSelected('CATEGORY_MANAGEMENT')}" + data-ng-click="moveToTab('CATEGORY_MANAGEMENT')" + translate="CATEGORY_MANAGEMENT"> + </button> + <a href={{monitorUrl}} target="_blank" ng-show="monitorUrl!=''" > + <button class="sdc-admin-top-bar-menu-monitor-btn" translate="MONITOR" data-tests-id="monitor"></button> + </a> + </nav> + + <div class="sdc-admin-body"> + <ng-include src="templateUrl" ng-if="true"></ng-include> + </div> +</div> diff --git a/catalog-ui/app/scripts/view-models/admin-dashboard/admin-dashboard.less b/catalog-ui/app/scripts/view-models/admin-dashboard/admin-dashboard.less new file mode 100644 index 0000000000..874a02c431 --- /dev/null +++ b/catalog-ui/app/scripts/view-models/admin-dashboard/admin-dashboard.less @@ -0,0 +1,49 @@ +.sdc-admin-container{ + height: 100%; + + .sdc-admin-top-bar-menu{ + .bg_k; + height: @top_nav_admin_height; + padding-left:260px; + .box-shadow(-1px 0px 3px 0px rgba(0, 0, 0, 0.33)); + position: absolute; + top: @header_height; + left: 0; + right: 0; + z-index: 2; + + .sdc-admin-top-bar-menu-tab{ + .b_17; + .hand; + height: 44px; + background-color: transparent; + position: relative; + padding: 0px 10px 0px 10px; + border: none; + outline: none; + margin-right: 15px; + &.selected { + outline: none; + border-bottom: solid 4px @color_t; + } + } + .sdc-admin-top-bar-menu-monitor-btn{ + .bg_a; + .c_6; + float: right; + border: none; + position: relative; + padding: 11px 24px; + } + } + + .sdc-admin-body{ + .bg_n; + padding: 40px 260px 60px 260px; + position: absolute; + top: @top_nav_admin_height; + left: 0; + right: 0; + bottom: 0; + } +} diff --git a/catalog-ui/app/scripts/view-models/admin-dashboard/category-management/category-management-view-model.ts b/catalog-ui/app/scripts/view-models/admin-dashboard/category-management/category-management-view-model.ts new file mode 100644 index 0000000000..a3ad7a2714 --- /dev/null +++ b/catalog-ui/app/scripts/view-models/admin-dashboard/category-management/category-management-view-model.ts @@ -0,0 +1,197 @@ +/*- + * ============LICENSE_START======================================================= + * SDC + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * 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. + * ============LICENSE_END========================================================= + */ +/// <reference path="../../../references"/> +module Sdc.ViewModels { + 'use strict'; + + interface ICategoryManagementViewModelScope extends ng.IScope { + SERVICE:string; + RESOURCE:string; + categoriesToShow: Array<Sdc.Services.ICategoryResource>; + serviceCategories: Array<Sdc.Services.ICategoryResource>; + resourceCategories: Array<Sdc.Services.ICategoryResource>; + selectedCategory: Sdc.Services.ICategoryResource; + selectedSubCategory: Sdc.Services.ICategoryResource; + modalInstance:ng.ui.bootstrap.IModalServiceInstance; + isLoading:boolean; + type:string; + namePattern:RegExp; + + selectCategory(category:Sdc.Services.ICategoryResource) :void; + selectSubCategory(subcategory:Sdc.Services.ICategoryResource) :void; + selectType(type:string) :void; + deleteCategory(category:Sdc.Services.ICategoryResource, subCategory:Sdc.Services.ICategoryResource) :void; + createCategoryModal(parentCategory:Sdc.Services.ICategoryResource) :void; + } + + export class CategoryManagementViewModel { + static '$inject' = [ + '$scope', + 'sdcConfig', + 'Sdc.Services.CacheService', + '$templateCache', + '$modal', + '$filter', + 'ValidationUtils', + 'ModalsHandler' + ]; + + constructor(private $scope:ICategoryManagementViewModelScope, + private sdcConfig:Models.IAppConfigurtaion, + private cacheService:Services.CacheService, + private $templateCache:ng.ITemplateCacheService, + private $modal:ng.ui.bootstrap.IModalService, + private $filter:ng.IFilterService, + private ValidationUtils: Sdc.Utils.ValidationUtils, + private ModalsHandler: Utils.ModalsHandler + ) { + + this.initScope(); + this.$scope.selectType(Sdc.Utils.Constants.ComponentType.SERVICE.toLocaleLowerCase()); + + } + + private initScope = ():void => { + let scope:ICategoryManagementViewModelScope = this.$scope; + scope.SERVICE = Sdc.Utils.Constants.ComponentType.SERVICE.toLocaleLowerCase(); + scope.RESOURCE = Sdc.Utils.Constants.ComponentType.RESOURCE.toLocaleLowerCase(); + + scope.namePattern = this.ValidationUtils.getValidationPattern('cssClasses'); + + scope.selectCategory = (category :Sdc.Services.ICategoryResource) => { + if(scope.selectedCategory !== category) { + scope.selectedSubCategory = null; + } + scope.selectedCategory = category; + }; + scope.selectSubCategory = (subcategory :Sdc.Services.ICategoryResource) => { + scope.selectedSubCategory = subcategory; + }; + scope.selectType = (type:string):void => { + if (scope.type !== type) { + scope.selectedCategory = null; + scope.selectedSubCategory = null; + } + + scope.type = type; + scope.categoriesToShow = scope[type + 'Categories']; + }; + + scope.createCategoryModal = (parentCategory:Sdc.Services.ICategoryResource):void => { + //can't create a sub category for service + if(parentCategory && scope.type === Sdc.Utils.Constants.ComponentType.SERVICE.toLowerCase()) { + return; + } + + let type:string = scope.type; + + let onOk = (newCategory :Sdc.Services.ICategoryResource):void => { + if(!parentCategory) { + scope[type + 'Categories'].push(newCategory); + }else{ + if(!parentCategory.subcategories) { + parentCategory.subcategories = []; + } + parentCategory.subcategories.push(newCategory); + } + }; + + let onCancel = ():void => { + + }; + + let modalOptions:ng.ui.bootstrap.IModalSettings = { + template: this.$templateCache.get('/app/scripts/view-models/admin-dashboard/add-category-modal/add-category-modal-view.html'), + controller: 'Sdc.ViewModels.AddCategoryModalViewModel', + size: 'sdc-xsm', + backdrop: 'static', + scope: scope, + resolve: { + parentCategory: function () { + return parentCategory; + }, + type: function () { + return type; + } + } + }; + + scope.modalInstance = this.$modal.open(modalOptions); + scope.modalInstance.result.then(onOk, onCancel); + + }; + + scope.deleteCategory = (category: Sdc.Services.ICategoryResource, subCategory: Sdc.Services.ICategoryResource): void => { + + let onOk = ():void => { + + scope.isLoading = true; + let type:string = scope.type; + + let onError = (response):void => { + scope.isLoading = false; + console.info('onFaild', response); + }; + + let onSuccess = (response: any) :void => { + let arr:Array<Sdc.Services.ICategoryResource>; + + if(!subCategory) { + arr = this.$scope[type + 'Categories']; + arr.splice(arr.indexOf(category), 1); + if(category === scope.selectedCategory) { + scope.selectedCategory = null; + scope.selectedSubCategory = null; + } + } else { + arr = category.subcategories; + arr.splice(arr.indexOf(subCategory), 1); + } + + scope.isLoading = false; + }; + + if(!subCategory) { + category.$delete({ + types: type+"s", + categoryId: category.uniqueId + } + , onSuccess, onError); + } else { + category.$deleteSubCategory({ + types: type+"s", + categoryId: category.uniqueId, + subCategoryId: subCategory.uniqueId, + } + , onSuccess, onError); + } + }; + let modelType:string = subCategory ? 'sub category' : 'cssClasses'; + let title:string = this.$filter('translate')("DELETE_CATEGORY_MODAL_HEADER", "{'modelType': '" + modelType +"' }"); + let message:string = this.$filter('translate')("DELETE_CATEGORY_MODAL_CATEGORY_NAME", "{'modelType': '" + modelType +"' }"); + + this.ModalsHandler.openConfirmationModal(title, message, false, 'sdc-xsm').then(onOk); + }; + + this.$scope.serviceCategories = this.cacheService.get('serviceCategories'); + this.$scope.resourceCategories = this.cacheService.get('resourceCategories'); + } + } +} diff --git a/catalog-ui/app/scripts/view-models/admin-dashboard/category-management/category-management-view.html b/catalog-ui/app/scripts/view-models/admin-dashboard/category-management/category-management-view.html new file mode 100644 index 0000000000..95a002d3d7 --- /dev/null +++ b/catalog-ui/app/scripts/view-models/admin-dashboard/category-management/category-management-view.html @@ -0,0 +1,53 @@ +<div data-ng-controller="Sdc.ViewModels.CategoryManagementViewModel" class="category-management"> + + <loader data-display="isLoading"></loader> + + <div class="row"> + + <div class="col-sm-6"> + + <h4> + <span class="hand selected" data-ng-click="selectType(SERVICE)" data-tests-id="servicecategoryheader" + data-ng-class="{'selected': type === SERVICE}" translate="SERVICE_CATEGORY_HEADER"></span> + <span class="hand" data-ng-click="selectType(RESOURCE)" data-tests-id="resourcecategoryheader" + data-ng-class="{'selected': type === RESOURCE}" translate="RESOURCE_CATEGORY_HEADER"></span> + </h4> + <span data-ng-click="createCategoryModal(null)" translate="ADD_CATEGORY" data-tests-id="newcategory"></span> + + <perfect-scrollbar class="perfect-scrollbar"> + <ul> + <li data-ng-repeat="category in categoriesToShow" + data-ng-class="{'selected': selectedCategory === category, 'gray': selectedSubCategory}" + data-ng-click="selectCategory(category)" + data-tests-id="{{ type === SERVICE ? 'servicecategory' : 'resourcecategory' }}"> + {{category.name}} + + <!--<button class="sprite e-sdc-small-icons-delete" data-ng-click="deleteCategory(category, null)" type="button"></button>--> + <!--button class="sprite e-sdc-small-icons-pad" data-ng-click="" type="button"></button--> + </li> + </ul> + </perfect-scrollbar> + </div> + + <div class="col-sm-6"> + + <h4><span translate="SUBCATEGORY_HEADER" data-tests-id="subcategoryheader"></span></h4> + <span data-ng-if="type === RESOURCE && selectedCategory" data-ng-click="selectedCategory ? createCategoryModal(selectedCategory) : ''" translate="ADD_SUBCATEGORY" data-tests-id="newsubcategory"></span> + + <perfect-scrollbar class="perfect-scrollbar"> + <ul> + <li data-ng-repeat="subcategory in selectedCategory.subcategories" + data-ng-class="{'selected': selectedSubCategory === subcategory}" + data-ng-click="selectSubCategory(subcategory)" + data-tests-id="subcategory"> + {{subcategory.name}} + + <!--<button class="sprite e-sdc-small-icons-delete" data-ng-click="deleteCategory(selectedCategory, subcategory)" type="button"></button>--> + <!--button class="sprite e-sdc-small-icon-pad" data-ng-click="" type="button"></button--> + </li> + </ul> + </perfect-scrollbar> + </div> + + </div> +</div> diff --git a/catalog-ui/app/scripts/view-models/admin-dashboard/category-management/category-management.less b/catalog-ui/app/scripts/view-models/admin-dashboard/category-management/category-management.less new file mode 100644 index 0000000000..011122c9e8 --- /dev/null +++ b/catalog-ui/app/scripts/view-models/admin-dashboard/category-management/category-management.less @@ -0,0 +1,118 @@ + +.category-management { + + .row { + display: table; + width: 70%; + min-width: 800px; + margin: auto; + + [class*="col-"] { + float: none; + display: table-cell; + vertical-align: top; + background-color: white; + border: 1px solid #c1c1c1; + padding: 0; + + &:not(:last-child) { + border-right: none; + } + + h4 { + float:left; + color:white; + background-color: rgb(155,168,176); + margin: 0; + padding: 0px 0px 0px 16px; + width: 100%; + height: 31px; + font-size: 15px; + + span{ + display: inline-block; + line-height: 30px; + margin-right: 5px; + padding: 0 7px; + + &.selected { + border-bottom: 2px #067ab4 solid; + } + } + } + h4+span{ + .hand; + float:right; + display: inline-block; + background-color: rgb(59,124,156); + text-align: center; + padding: 5.5px 0px; + width: 60px; + color: white; + position: absolute; + top: 0; + right: 0; + z-index: 1; + color: white; + } + + + .perfect-scrollbar { + width: 100%; + height: 500px; + margin-top: 40px; + margin-bottom: 15px; + } + + ul { + clear: both; + margin: 5px 0 10px 0; + list-style-type: none; + padding: 0; + position: relative; + + li{ + .hand; + padding: 0 8px; + text-indent: 9px; + font-size: 13px; + line-height: 25px; + border: 1px solid white; + border-right: none; + border-left: none; + margin-right: 5px; + + button { + background-color: transparent; + border: none; + float: right; + margin: 5px 3px; + display: none; + } + + &:hover { + background-color: #d9e6ec; + color: #3b7b9b; + border-color: #d9e6ec; + + button { + display: inline-block; + } + } + &.selected { + background-color: rgb(219,230,236); + color: #3b7b9b; + border-color: rgba(59, 123, 155, 0.42); + + &.gray { + background-color: rgba(155, 168, 176, 0.09); + border-color: white; + } + } + + } + } + } + } + +} diff --git a/catalog-ui/app/scripts/view-models/admin-dashboard/ecomp/ecomp-view.html b/catalog-ui/app/scripts/view-models/admin-dashboard/ecomp/ecomp-view.html new file mode 100644 index 0000000000..7c89b545c5 --- /dev/null +++ b/catalog-ui/app/scripts/view-models/admin-dashboard/ecomp/ecomp-view.html @@ -0,0 +1 @@ +<div></div> diff --git a/catalog-ui/app/scripts/view-models/admin-dashboard/user-management/user-management-view-model.ts b/catalog-ui/app/scripts/view-models/admin-dashboard/user-management/user-management-view-model.ts new file mode 100644 index 0000000000..3921d0cf8f --- /dev/null +++ b/catalog-ui/app/scripts/view-models/admin-dashboard/user-management/user-management-view-model.ts @@ -0,0 +1,220 @@ +/*- + * ============LICENSE_START======================================================= + * SDC + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * 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. + * ============LICENSE_END========================================================= + */ +/// <reference path="../../../references"/> +module Sdc.ViewModels { + + import IUserProperties = Sdc.Models.IUserProperties; + 'use strict'; + + interface IUserManagementViewModelScope extends ng.IScope { + sdcConfig:Models.IAppConfigurtaion; + usersList: Array<Models.IUserProperties>; + isLoading: boolean; + isNewUser: boolean; + sortBy:string; + reverse:boolean; + tableHeadersList:any; + roles:Array<string>; + newUser: Models.IUser; + currentUser: Sdc.Services.IUserResource; + userIdValidationPattern: RegExp; + editForm:ng.IFormController; + getAllUsers():void; + editUserRole(user:IUserProperties); + sort(sortBy:string): void; + createUser(): void; + deleteUser(userId:string) : void; + onEditUserPressed(user:IUserProperties): void; + saveUserChanges(user:IUserProperties) :void; + getTitle(role:string): string; + clearForm():void; + + } + + + export class UserManagementViewModel { + static '$inject' = [ + '$scope', + 'sdcConfig', + 'Sdc.Services.UserResourceService', + '$templateCache', + '$modal', + 'UserIdValidationPattern', + '$filter', + 'ModalsHandler' + ]; + + constructor(private $scope:IUserManagementViewModelScope, + private sdcConfig:Models.IAppConfigurtaion, + private userResourceService:Sdc.Services.IUserResourceClass, + private $templateCache:ng.ITemplateCacheService, + private $modal:ng.ui.bootstrap.IModalService, + private UserIdValidationPattern:RegExp, + private $filter:ng.IFilterService, + private ModalsHandler: Utils.ModalsHandler + ) { + + this.initScope(); + + } + + + + private getAllUsers = ():void => { + this.$scope.isLoading = true; + + let onError = (response) => { + this.$scope.isLoading = false; + console.info('onFaild', response); + }; + let onSuccess = (response: Array<Models.IUserProperties>) => { + this.$scope.usersList = response; + _.forEach(this.$scope.usersList,(user:any,i:number)=>{ + user.index = i; + }); + this.$scope.isLoading = false; + }; + this.userResourceService.getAllUsers(onSuccess, onError); + }; + + private updateUserFilterTerm = (user: IUserProperties): void =>{ + user.filterTerm = user.firstName + ' ' + user.lastName + ' ' + user.userId + ' ' + user.email + ' ' + user.role + ' ' + this.$filter('date')(user.lastLoginTime, "MM/dd/yyyy"); + }; + + private initScope = ():void => { + let self=this; + + this.$scope.tableHeadersList = [ + {title: "First Name", property: 'firstName'}, + {title: "Last Name", property: 'lastName'}, + {title: this.$filter('translate')("USER_MANAGEMENT_TABLE_HEADER_USER_ID"), property: 'userId'}, + {title: "Email", property: 'email'}, + {title: "Role", property: 'role'}, + {title: "Last Active", property: 'lastLoginTime'} + ]; + this.$scope.userIdValidationPattern = this.UserIdValidationPattern; + this.$scope.sortBy = 'lastLoginTime'; + this.$scope.reverse = false; + this.$scope.roles = this.sdcConfig.roles; + this.$scope.isNewUser = false; + this.$scope.currentUser = this.userResourceService.getLoggedinUser(); + this.getAllUsers(); + + let resource : Services.IUserResource = <Services.IUserResource>{}; + this.$scope.newUser = new Sdc.Models.User(resource); + + this.$scope.sort = (sortBy:string):void => {//default sort by descending last update. default for alphabetical = ascending + this.$scope.isNewUser = false; + this.$scope.reverse = (this.$scope.sortBy === sortBy) ? ( !this.$scope.reverse) : this.$scope.reverse = false; + this.$scope.sortBy = sortBy; + }; + + this.$scope.createUser = () : void => { + + let onError = (response) => { + this.$scope.isLoading = false; + console.info('onFaild', response); + }; + + let onSuccess = (response: Models.IUserProperties) => { + this.$scope.newUser.resource['index'] = this.$scope.usersList.length; + this.$scope.newUser.resource.lastLoginTime = "0"; + this.$scope.newUser.resource.status = response.status; + this.updateUserFilterTerm(this.$scope.newUser.resource); + this.$scope.usersList.unshift(this.$scope.newUser.resource); + this.$scope.isNewUser = true; + this.$scope.sortBy = 'index'; + this.$scope.reverse = true; + this.$scope.isLoading = false; + this.$scope.newUser = new Sdc.Models.User(null); + this.$scope.editForm.$setPristine(); + let _self = this; + setTimeout(function () { + _self.$scope.isNewUser = false; + }, 7000); + }; + this.userResourceService.createUser({ userId: this.$scope.newUser.resource.userId, role: this.$scope.newUser.resource.role}, onSuccess, onError); + }; + + + this.$scope.onEditUserPressed = (user:IUserProperties): void => { + user.isInEditMode = true; + user.tempRole = user.role; + }; + + this.$scope.editUserRole = (user:IUserProperties): void => { + let roleBeforeUpdate: string = user.role; + user.role= user.tempRole; + + let onError = (response) => { + this.$scope.isLoading = false; + user.role = roleBeforeUpdate; + console.info('onFaild', response); + }; + let onSuccess = (response: any) => { + this.$scope.isLoading = false; + user.tempRole = user.role; + this.updateUserFilterTerm(user); + }; + + this.userResourceService.editUserRole({ id: user.userId, role: user.role}, onSuccess, onError); + }; + + this.$scope.saveUserChanges = (user:IUserProperties): void => { + if(user.tempRole != user.role){ + this.$scope.editUserRole(user) + } + user.isInEditMode = false; + }; + + this.$scope.deleteUser = (userId:string): void => { + + let onOk = ():void => { + this.$scope.isLoading = true; + + let onError = (response):void => { + this.$scope.isLoading = false; + console.info('onFaild', response); + }; + + let onSuccess = (response: any) :void => { + _.remove(this.$scope.usersList, {userId: userId }); + this.$scope.isLoading = false; + }; + this.userResourceService.deleteUser({ id: userId}, onSuccess, onError); + }; + + let title:string = this.$filter('translate')("USER_MANAGEMENT_VIEW_DELETE_MODAL_TITLE"); + let message:string = this.$filter('translate')("USER_MANAGEMENT_VIEW_DELETE_MODAL_TEXT"); + this.ModalsHandler.openConfirmationModal(title, message, false).then(onOk); + }; + + this.$scope.getTitle = (role:string):string =>{ + return role.toLowerCase().replace('governor','governance_Rep').replace('_',' '); + }; + + this.$scope.clearForm =():void =>{ + if(!this.$scope.editForm['contactId'].$viewValue && !this.$scope.editForm['role'].$viewValue){ + this.$scope.editForm.$setPristine(); + } + }; + } + } +} diff --git a/catalog-ui/app/scripts/view-models/admin-dashboard/user-management/user-management-view.html b/catalog-ui/app/scripts/view-models/admin-dashboard/user-management/user-management-view.html new file mode 100644 index 0000000000..26e720b044 --- /dev/null +++ b/catalog-ui/app/scripts/view-models/admin-dashboard/user-management/user-management-view.html @@ -0,0 +1,102 @@ +<div ng-controller="Sdc.ViewModels.UserManagementViewModel"> + <loader data-display="isLoading"></loader> + <div class="sdc-user-management-top-bar"> + <div class="sdc-user-management-top-bar-search-container"> + <label class="sdc-user-management-top-bar-search-text">Search User</label> + <input type="text" class="sdc-user-management-top-bar-form-input" placeholder="{{ USER_MANAGEMENT_SEARCH_LABEL | translate }}" data-ng-model="search.filterTerm" ng-model-options="{ debounce: 500 }" data-tests-id="searchbox" /> + <span class="w-sdc-search-icon" data-ng-class="{'cancel':search.filterTerm, 'magnification':!search.filterTerm}" data-ng-click="search.filterTerm=''" ></span> + </div> + <div class="vertical-border-container"> + <div class="vertical-border"></div> + </div> + <form class="sdc-user-management-top-bar-create-user-container w-sdc-form" name="editForm"> + <label class="sdc-user-management-top-bar-title">Create New User</label> + <div class="sdc-user-management-top-bar-wrapper"> + <div class="i-sdc-form-item sdc-user-management-top-bar-form-container" data-ng-class="{error:(editForm.contactId.$dirty && editForm.contactId.$invalid)}"> + <input ng-focus="search.filterTerm=''" type="text" + data-ng-model="newUser.resource.userId" + class="i-sdc-form-input" + placeholder="{{ USER_MANAGEMENT_SEARCH_TEXT | translate}}" + data-ng-model-options="{ updateOn: 'default blur', debounce: { 'default': 750, 'blur': 0 } }" + name="contactId" + data-ng-pattern="userIdValidationPattern" + data-ng-change="clearForm()" + data-ng-blur="clearForm()" + data-required + data-tests-id="newuserid" /> + + <div class="input-error" data-ng-show="editForm.contactId.$dirty && editForm.contactId.$invalid"> + <span ng-show="editForm.contactId.$error.required" translate="NEW_USER_ERROR_USER_ID_REQUIRED"></span> + <span ng-show="editForm.contactId.$error.pattern" translate="NEW_USER_ERROR_USER_ID_NOT_VALID"></span> + </div> + </div> + <div class="i-sdc-form-item sdc-user-management-top-bar-form-container" data-ng-class="{error:(editForm.role.$dirty && editForm.role.$invalid + && editForm.contactId.$viewValue)}"> + <select class="i-sdc-form-select capitalize" + data-required + name="role" + data-tests-id="selectrole" + data-ng-model = "newUser.resource.role" + data-ng-options="role as (getTitle(role)) for role in roles | orderBy:'role'" + ng-focus="search.filterTerm=''"> + <option value="">Select Role</option> + </select> + <div class="input-error" data-ng-show="editForm.role.$dirty && editForm.role.$invalid && editForm.contactId.$viewValue"> + <span ng-show="editForm.role.$error.required" translate="NEW_USER_ERROR_ROLE_REQUIRED"></span> + </div> + </div> + <button data-tests-id="creategreen" data-ng-disabled="editForm.$invalid" class="sdc-user-management-top-bar-create-btn" ng-click="search.filterTerm = '' ; createUser()">Create</button> + </div> + </form> + </div> + + + <div class="sdc-user-management-table-container-flex"> + + <div class="sdc-user-management-table"> + <div class="head sdc-user-management-flex-container"> + <div class="sdc-user-management-table-header head-row hand sdc-user-management-flex-item" data-tests-id="th{{header.title}}" ng-repeat="header in tableHeadersList" ng-click="sort(header.property)">{{header.title}} + <span ng-if="sortBy === header.property" class="sdc-user-management-table-header-sort-arrow" data-ng-class="{'down': reverse, 'up':!reverse}"> </span> + </div> + <div class="sdc-user-management-table-no-text-header head-row sdc-user-management-flex-item"></div> + <div class="sdc-user-management-table-no-text-header head-row sdc-user-management-flex-item"></div> + </div> + + <div class="body"> + <perfect-scrollbar scroll-y-margin-offset="0" include-padding="true" class="scrollbar-container"> + <div ng-init="user.filterTerm = user.firstName + ' ' + user.lastName + ' ' + user.userId + ' ' + user.email + ' ' + user.role + ' ' + (user.lastLoginTime | date: 'MM/dd/yyyy')" + ng-repeat="user in usersList | filter: search | orderBy:sortBy:reverse" + data-ng-class="{'sdc-user-management-table-new-user-row': (isNewUser && $first), 'sdc-user-management-table-row-edit-mode': user.isInEditMode}" + class="sdc-user-management-flex-container data-row" data-tests-id="tdRow"> + + <div sdc-smart-tooltip class="sdc-user-management-table-col-general sdc-user-management-flex-item" data-tests-id="td{{tableHeadersList[0].title}}">{{user.firstName || '---'}}</div> + <div sdc-smart-tooltip class="sdc-user-management-table-col-general sdc-user-management-flex-item" data-tests-id="td{{tableHeadersList[1].title}}">{{user.lastName || '---' }}</div> + <div class="sdc-user-management-table-col-userid sdc-user-management-flex-item" data-tests-id="td{{tableHeadersList[2].title}}">{{user.userId || '---'}}</div> + <div sdc-smart-tooltip class="sdc-user-management-table-col-general sdc-user-management-flex-item" data-tests-id="td{{tableHeadersList[3].title}}">{{user.email || '---'}}</div> + <div class="sdc-user-management-table-col-general sdc-user-management-flex-item" data-tests-id="td{{tableHeadersList[4].title}}"> + <div class="sdc-user-management-table-role-select capitalize sdc-user-management-table-role-label" + data-ng-if="!user.isInEditMode" + data-ng-bind="getTitle(user.role)"></div> + <select class="sdc-user-management-table-role-select capitalize" + data-tests-id="tdselectrole" + data-ng-if="user.isInEditMode" + data-ng-model="user.tempRole" + data-ng-options="role as (getTitle(role)) for role in roles | orderBy:'role'"> + </select> + </div> + <div class="sdc-user-management-table-col-general sdc-user-management-flex-item" data-tests-id="td{{tableHeadersList[5].title}}">{{user.lastLoginTime == 0 ? 'Waiting' : (user.lastLoginTime | date:'MM/dd/yyyy')}}</div> + <div class="sdc-user-management-table-btn-col sdc-user-management-flex-item"> + <button data-ng-disabled="user.isInEditMode" data-ng-hide="user.isInEditMode || currentUser.userId === user.userId" class="sdc-user-management-table-edit-btn" ng-click="onEditUserPressed(user)" data-tests-id="updateuser{{user.userId}}"> </button> + <button data-ng-show="user.isInEditMode" class="sdc-user-management-table-save-btn" ng-click="saveUserChanges(user)" data-tests-id="tdsave"> </button> + </div> + <div class="sdc-user-management-table-btn-col sdc-user-management-flex-item"> + <button data-ng-hide="currentUser.userId === user.userId" class="sdc-user-management-table-delete-btn" ng-click="deleteUser(user.userId)" data-tests-id="delete{{user.userId}}"> </button> + </div> + + </div> + </perfect-scrollbar> + </div> + + </div> + </div> +</div> diff --git a/catalog-ui/app/scripts/view-models/admin-dashboard/user-management/user-management.less b/catalog-ui/app/scripts/view-models/admin-dashboard/user-management/user-management.less new file mode 100644 index 0000000000..934faab9e7 --- /dev/null +++ b/catalog-ui/app/scripts/view-models/admin-dashboard/user-management/user-management.less @@ -0,0 +1,251 @@ +.sdc-user-management-top-bar { + display: flex; + width: 100%; + label { + .i_17; + } + .sdc-user-management-top-bar-form-input, + .sdc-user-management-top-bar-form-select { + .b_9; + color: @color_b; + height: 28px; + padding-left: 10px; + border-radius: 2px; + border: 1px solid @border_color_f; + } + + .sdc-user-management-top-bar-search-container { + display: flex; + flex-direction: column; + position: relative; + width: 400px; + + label { + margin-bottom: 20px; + } + + .w-sdc-search-icon { + right: 11px; + top: 49px; + } + } + .vertical-border-container { + min-width: 50px; + margin: 0px auto; + + .vertical-border { + + width: 1px; + height: 70px; + background-color: @color_e; + display: table; + margin: 0 auto; + } + } + + .sdc-user-management-top-bar-wrapper { + display: flex; + } + + .sdc-user-management-top-bar-title { + .i_17; + font-weight: bold; + } + + .sdc-user-management-top-bar-create-user-container { + + display: flex; + flex-direction: column; + position: relative; + float: right; + padding-top: 0px; + text-align: left; + width: 650px; + + label { + margin-bottom: 20px; + } + + .sdc-user-management-top-bar-form-container { + width: 233px; + margin-right: 35px; + } + + .sdc-user-management-top-bar-create-btn { + .w-sdc-btn-light-green; + height: 30px; + width: 100px; + line-height: 0px; + padding-bottom: 3px; + margin-right: 0px; + } + } +} + + +.sdc-user-management-table-container-flex { + height: 650px; + margin-top: 35px; + .sdc-user-management-table { + width: 100%; + border: 1px solid @color_m; + .head { + .bg_m; + .head-row { + .c_18; + font-weight: bold; + + border-right: 1px solid @border_color_d; + + .sdc-user-management-table-header-sort-arrow { + display: inline-block; + background-color: transparent; + border: none; + .c_9; + width: 0; + height: 0; + float: right; + margin: 8px 8px 0px 0px; + &.up { + border-left: 5px solid transparent; + border-right: 5px solid transparent; + border-bottom: 5px solid; + } + &.down { + border-left: 5px solid transparent; + border-right: 5px solid transparent; + border-top: 5px solid; + } + } + } + .sdc-user-management-table-header:hover { + .bg_j; + } + + } + .body { + .scrollbar-container { + max-height: 421px; + .perfect-scrollbar; + } + .b_9; + + .data-row { + &:nth-of-type(odd) { + .bg_c; + } + &.sdc-user-management-table-new-user-row { + + animation: change 7s step-end both; + + @keyframes change { + from { + color: @color_z + } + to { + color: @color_b + } + } + } + &.sdc-user-management-table-row-edit-mode { + .bg_j; + } + div { + + border-right: 1px solid @border_color_d; + + &:last-child { + border-right: none; + } + + .sdc-user-management-table-role-select { + background-color: transparent; + border: 0; + width: 100%; + + } + .sdc-user-management-table-role-label { + margin-left:4px; + } + + } + + } + .data-row:hover { + .bg_j; + } + + } + + .sdc-user-management-table-btn-col { + + line-height: 0px; + text-align: center; + .sdc-user-management-table-delete-btn { + background-color: transparent; + border: none; + .sprite; + .sprite.e-sdc-small-icon-delete; + opacity: 0.7; + } + .sdc-user-management-table-edit-btn { + background-color: transparent; + border: none; + .sprite; + .e-sdc-small-icon-pencil; + opacity: 0.7; + } + .sdc-user-management-table-save-btn { + background-color: transparent; + border: none; + .sprite; + .sprite.e-sdc-green-save; + } + } + + } + + .sdc-user-management-flex-container { + display: flex; + } + + .sdc-user-management-flex-item { + width:10px; + padding: 5px; + text-align: center; + } + + .sdc-user-management-flex-item:nth-child(1) { + flex-grow: 5; + } + + .sdc-user-management-flex-item:nth-child(2) { + flex-grow: 7; + } + + .sdc-user-management-flex-item:nth-child(3) { + flex-grow: 4; + } + + .sdc-user-management-flex-item:nth-child(4) { + flex-grow: 8; + } + + .sdc-user-management-flex-item:nth-child(5) { + flex-grow: 8; + } + + .sdc-user-management-flex-item:nth-child(6) { + flex-grow: 8; + } + + .sdc-user-management-flex-item:nth-child(7) { + flex-grow: 1; + } + + .sdc-user-management-flex-item:nth-child(8) { + flex-grow: 1; + } + +} + |