summaryrefslogtreecommitdiffstats
path: root/ecomp-portal-FE-common/client/app/views/widget-onboarding/widget-details-dialog
diff options
context:
space:
mode:
Diffstat (limited to 'ecomp-portal-FE-common/client/app/views/widget-onboarding/widget-details-dialog')
-rw-r--r--ecomp-portal-FE-common/client/app/views/widget-onboarding/widget-details-dialog/widget-details.controller.js381
-rw-r--r--ecomp-portal-FE-common/client/app/views/widget-onboarding/widget-details-dialog/widget-details.controller.spec.js154
-rw-r--r--ecomp-portal-FE-common/client/app/views/widget-onboarding/widget-details-dialog/widget-details.modal.html156
-rw-r--r--ecomp-portal-FE-common/client/app/views/widget-onboarding/widget-details-dialog/widget-details.modal.less102
4 files changed, 793 insertions, 0 deletions
diff --git a/ecomp-portal-FE-common/client/app/views/widget-onboarding/widget-details-dialog/widget-details.controller.js b/ecomp-portal-FE-common/client/app/views/widget-onboarding/widget-details-dialog/widget-details.controller.js
new file mode 100644
index 00000000..0a9dd12c
--- /dev/null
+++ b/ecomp-portal-FE-common/client/app/views/widget-onboarding/widget-details-dialog/widget-details.controller.js
@@ -0,0 +1,381 @@
+/*-
+ * ================================================================================
+ * 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 WidgetOnboardingDetailsModalCtrl {
+ constructor($scope, $log, $interval, applicationsService, adminsService, microserviceService, widgetsCatalogService, errorMessageByCode, ECOMP_URL_REGEX, $window,userProfileService, confirmBoxService, $cookies) {
+
+ this.appUpdate = function(){
+ this.hasSelectedApp = false;
+ this.appCounter = 0;
+ for(var i = 0; i < this.availableApps.length; i++){
+ if(this.availableApps[i].isSelected){
+ this.appCounter++;
+ if(!this.hasSelectedApp)
+ this.hasSelectedApp = true;
+ }
+ if(this.availableApps[i].isSelected
+ && this.availableApps[i].roles.length == 0){
+ var index = i;
+ this.availableRoles = [];
+ adminsService.getRolesByApp(this.availableApps[i].id).then(roles => {
+ for(var i = 0; i < roles.length; i++){
+ this.availableRoles.push({
+ id: roles[i].id,
+ name: roles[i].name,
+ isSelected: false,
+ });
+ }
+ this.availableApps[index].roles = this.availableRoles;
+ });
+ }
+ }
+ this.allRoleSelected = true;
+ this.checkRoleSelected();
+ }
+
+ this.roleUpdate = function(app){
+ this.allRoleSelected = true;
+ for(var i = 0; i < app.roles.length; i++){
+ if(app.roles[i].isSelected){
+ app.roleSelected = true;
+ this.checkRoleSelected();
+ return;
+ }
+ }
+ app.roleSelected = false;
+ this.checkRoleSelected();
+ }
+
+ this.checkRoleSelected = function(){
+ for(var i = 0; i < this.availableApps.length; i++){
+ if(this.availableApps[i].isSelected
+ && !this.availableApps[i].roleSelected){
+ this.allRoleSelected = false;
+ return;
+ }
+ }
+ }
+
+ this.getAppName = function(appId){
+ for(var i = 0; i < this.availableApps.length; i++){
+ if(this.availableApps[i].id == appId){
+ return this.availableApps[i].name;
+ }
+ }
+ }
+
+ let newWidgetModel = {
+ name: null,
+ roleId: null,
+ roleName: null,
+ appId: null,
+ appName: null,
+ url: null,
+ showAppOptions: false,
+ showRoleOptions: false,
+ hasSelectedApp: false
+ };
+
+ let getAvailableApps = () => {
+
+ if(this.isEditMode == false){
+ applicationsService.getAppsForSuperAdminAndAccountAdmin().then(apps => {
+ this.availableApps=[];
+ for(var i=0;i<apps.length;i++) {
+ if (!apps[i].restrictedApp) {
+ this.availableApps.push({
+ id: apps[i].id,
+ name: apps[i].name,
+ roles: [],
+ roleSelected: false,
+ isSelected: false,
+ });
+ }
+ }
+ }).catch(err => {
+ $log.error(err);
+ });
+ }
+ else if(this.isEditMode == true){
+ if(this.widget.allowAllUser == "Y")
+ this.widget.allUser = true;
+ applicationsService.getAppsForSuperAdminAndAccountAdmin().then(apps => {
+ this.availableApps=[];
+ let selectedApps = {};
+ var availableApps = this.availableApps;
+ this.allRoleSelected = true;
+ for(var i=0; i < this.widget.widgetRoles.length; i++){
+ if(selectedApps[this.widget.widgetRoles[i].app.appId] != undefined)
+ selectedApps[this.widget.widgetRoles[i].app.appId] += this.widget.widgetRoles[i].roleId + ";" + this.widget.widgetRoles[i].roleName + ";";
+ else{
+ selectedApps[this.widget.widgetRoles[i].app.appId] = this.widget.widgetRoles[i].roleId + ";" + this.widget.widgetRoles[i].roleName + ";";
+ this.appCounter++;
+ }
+ }
+ apps.forEach(function(app, index){
+ availableApps.push({
+ id: app.id,
+ name: app.name,
+ roles: [],
+ roleSelected: false,
+ isSelected: false,
+ });
+ if(selectedApps[app.id] != undefined){
+ adminsService.getRolesByApp(app.id).then(roles => {
+ var role = selectedApps[app.id].split(';');
+ var selectedRoles = [];
+ var n = 0;
+ while((n+1) < role.length){
+ selectedRoles.push({
+ id: role[n++],
+ name: role[n++],
+ isSelected: true,
+ });
+ }
+ for(var m = 0; m < roles.length; m++){
+ var hasSelected = true;
+ for(var n = 0; n < selectedRoles.length; n++){
+ if(selectedRoles[n].id == roles[m].id){
+ hasSelected = false;
+ break;
+ }
+ }
+ if(hasSelected){
+ selectedRoles.push({
+ id: roles[m].id,
+ name: roles[m].name,
+ isSelected: false,
+ });
+ }
+ }
+ availableApps[index].roleSelected = true;
+ availableApps[index].isSelected = true;
+ availableApps[index].roles = selectedRoles;
+ });
+ }
+ })
+ })
+ }
+ };
+
+ let getAvailableServices = () =>{
+ microserviceService.getServiceList().then(services => {
+ this.availableServices = [];
+ for(var i = 0; i < services.length; i++){
+ this.availableServices.push({
+ id: services[i].id,
+ name: services[i].name,
+ option: services[i].name + ": " + services[i].url
+ });
+
+ if(this.widget.service != null && this.widget.service.id == services[i].id){
+ this.widget.serviceURL = this.availableServices[i];
+ }
+ }
+ }).catch(err => {
+ $log.error(err);
+ });
+ }
+
+
+ let init = () => {
+ $log.info('WidgetOnboardingDetailsModalCtrl::init');
+ this.widgetsList = [];
+ this.duplicatedName = true;
+ this.allRoleSelected = false;
+ this.appCounter = 0;
+ this.isSaving = false;
+ this.allUser = false;
+ this.emptyWidgetName = false;
+
+ if ($scope.ngDialogData && $scope.ngDialogData.widget) {
+ this.isEditMode = true;
+ this.allRoleSelected = true;
+ this.widget = _.clone($scope.ngDialogData.widget);
+ } else {
+ this.isEditMode = false;
+ this.widget = _.clone(newWidgetModel);
+ }
+
+ widgetsCatalogService.getManagedWidgets().then(res => {
+ for(var i = 0; i < res.length; i++){
+ this.widgetsList.push(res[i].name);
+ }
+ }).catch(err => {
+ $log.error('WidgetOnboardingDetailsModalCtrl::init error: ' + err);
+ }).finally(()=> {
+ this.isLoadingTable = false;
+ });
+ getAvailableApps();
+ getAvailableServices();
+ };
+ this.ECOMP_URL_REGEX = ECOMP_URL_REGEX;
+ this.conflictMessages = {};
+ this.scrollApi = {};
+
+ let resetConflict = fieldName => {
+ delete this.conflictMessages[fieldName];
+ if($scope.widgetForm[fieldName]){
+ $scope.widgetForm[fieldName].$setValidity('conflict', true);
+ }
+ };
+
+ this.updateSelectedRole = () => {
+ if (!this.selectedRole) {
+ return;
+ }
+ this.widget.RoleId = this.selectedRole.id;
+ this.widget.RoleName = this.selectedRole.name;
+ };
+
+ let emptyCookies = () => {
+ userProfileService.getUserProfile()
+ .then(profile=> {
+ $log.info('AppDetailsModalCtrl::emptyCookies profile: ', profile);
+ $scope.orgUserId = profile.orgUserId;
+ $log.info('user has the following orgUserId: ' + profile.orgUserId);
+ if ($cookies.getObject($scope.orgUserId + '_widget') != undefined && $cookies.getObject($scope.orgUserId + '_widget') != null) {
+ $cookies.remove($scope.orgUserId + '_widget');
+ }
+ });
+ };
+
+ this.updateWidgetName = () => {
+ for(var i = 0; i < this.widgetsList.length; i++){
+ if(this.widget.name.toUpperCase() == this.widgetsList[i].toUpperCase()){
+ this.duplicatedName = false;
+ return;
+ }
+ }
+ this.duplicatedName = true;
+ };
+
+ this.saveChanges = () => {
+
+ if(!this.isEditMode)
+ this.updateWidgetName();
+
+ if(this.duplicatedName == false
+ || this.widget.name == ''
+ || this.widget.name == undefined){
+ this.emptyWidgetName = true;
+ return;
+ }
+
+ if((this.widget.file == undefined && !this.isEditMode) ||
+ (!this.widget.allUser && this.appCounter == 0) ||
+ this.widget.name == null ||
+ (!this.widget.allUser && !this.allRoleSelected) ||
+ this.widget.saving == true)
+ return;
+
+
+ this.widget.saving = true;
+ var selectedRoles = [];
+ if(!this.widget.allUser){
+ for(var i = 0; i < this.availableApps.length; i++){
+ if(this.availableApps[i].isSelected){
+ for(var n = 0; n < this.availableApps[i].roles.length; n++) {
+ if(this.availableApps[i].roles[n].isSelected){
+ var role = {
+ app: {
+ appId: this.availableApps[i].id
+ },
+ roleId: this.availableApps[i].roles[n].id,
+ roleName: this.availableApps[i].roles[n].name,
+ };
+ selectedRoles.push(role);
+ }
+ }
+ }
+ }
+ }
+
+ var allowAllUser = 0;
+ if(this.widget.allUser)
+ allowAllUser = 1;
+
+ var serviceId = null;
+ if(this.widget.serviceURL != null &&
+ this.widget.serviceURL != undefined){
+ serviceId = this.widget.serviceURL.id;
+ }
+
+
+ var file_loc = this.widget.name + ".zip";
+ var newWidget = {
+ name: this.widget.name,
+ desc: this.widget.desc,
+ widgetRoles: selectedRoles,
+ fileLocation: file_loc,
+ allowAllUser: allowAllUser,
+ serviceId: serviceId
+ };
+
+ if(this.isEditMode){
+
+ if(this.widget.file != undefined){
+ widgetsCatalogService.updateWidgetWithFile(this.widget.file, this.widget.id, newWidget).then(res => {
+ if(!res.valid){
+ if(!res.error){
+ confirmBoxService.showInformation("Could not save. Please retry.");
+ this.widget.saving = false;
+ return;
+ }
+ confirmBoxService.showInformation(res.error);
+ this.widget.saving = false;
+ return;
+ }
+ $scope.closeThisDialog(true);
+ this.widget.saving = false;
+ });
+ }
+ else{
+ widgetsCatalogService.updateWidget(this.widget.id, newWidget)
+ .then(() => {
+ $scope.closeThisDialog(true);
+ });
+ }
+ }
+ else{
+ widgetsCatalogService.createWidget(newWidget, this.widget.file).then(res => {
+ if(!res.valid){
+ if(!res.error)
+ confirmBoxService.showInformation("Could not save. Please retry.");
+ else
+ confirmBoxService.showInformation(res.error);
+ this.widget.saving = false;
+ return;
+ }
+ $scope.closeThisDialog(true);
+ this.widget.saving = false;
+ });
+ }
+ };
+ init();
+ $scope.$on('$stateChangeStart', e => {
+ e.preventDefault();
+ });
+ }
+ }
+ WidgetOnboardingDetailsModalCtrl.$inject = ['$scope', '$log', '$interval', 'applicationsService', 'adminsService', 'microserviceService', 'widgetsCatalogService', 'errorMessageByCode', 'ECOMP_URL_REGEX', '$window','userProfileService', 'confirmBoxService', '$cookies'];
+ angular.module('ecompApp').controller('WidgetOnboardingDetailsModalCtrl', WidgetOnboardingDetailsModalCtrl);
+})();
diff --git a/ecomp-portal-FE-common/client/app/views/widget-onboarding/widget-details-dialog/widget-details.controller.spec.js b/ecomp-portal-FE-common/client/app/views/widget-onboarding/widget-details-dialog/widget-details.controller.spec.js
new file mode 100644
index 00000000..1762fadb
--- /dev/null
+++ b/ecomp-portal-FE-common/client/app/views/widget-onboarding/widget-details-dialog/widget-details.controller.spec.js
@@ -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.
+ * ================================================================================
+ */
+// 'use strict';
+// describe('Controller: WidgetDetailsModalCtrl', ()=> {
+// /**
+// * INITIALIZATION
+// */
+// beforeEach(module('testUtils'));
+// beforeEach(module('ecompApp'));
+//
+// let promisesTestUtils;
+// //destroy $http default cache before starting to prevent the error 'default cache already exists'
+// //_promisesTestUtils_ comes from testUtils for promises resolve/reject
+// beforeEach(inject((_CacheFactory_, _promisesTestUtils_)=> {
+// _CacheFactory_.destroyAll();
+// promisesTestUtils = _promisesTestUtils_;
+// }));
+//
+// let widgetDetails, scope, $controller, $q, $rootScope, $log, widgetsService, errorMessageByCode, ECOMP_URL_REGEX;
+// let deferredAdminApps, deferredUserProfile;
+// let applicationsServiceMock, widgetsServiceMock, userProfileServiceMock;
+// beforeEach(inject((_$controller_, _$q_, _$rootScope_, _$log_)=> {
+// [$controller, $q, $rootScope, $log] = [_$controller_, _$q_, _$rootScope_, _$log_];
+//
+// deferredAdminApps = $q.defer();
+// deferredUserProfile = $q.defer();
+// /*applicationsServiceMock = {
+// getAppsForSuperAdminAndAccountAdmin: () => {
+// var promise = () => {return deferredAdminApps.promise};
+// var cancel = jasmine.createSpy();
+// return {
+// promise: promise,
+// cancel: cancel
+// }
+// }
+// };*/
+//
+// widgetsServiceMock = {
+// updateWidget: () => {
+// var promise = () => {return deferredAdminApps.promise};
+// var cancel = jasmine.createSpy();
+// return {
+// promise: promise,
+// cancel: cancel
+// }
+// },
+// createWidget: () => {
+// var promise = () => {return deferredAdminApps.promise};
+// var cancel = jasmine.createSpy();
+// return {
+// promise: promise,
+// cancel: cancel
+// }
+// }
+// };
+//
+// userProfileServiceMock = jasmine.createSpyObj('userProfileServiceMock',['getUserProfile']);
+// userProfileServiceMock.getUserProfile.and.returnValue(deferredUserProfile.promise);
+//
+// applicationsServiceMock = jasmine.createSpyObj('applicationsServiceMock',['getAppsForSuperAdminAndAccountAdmin']);
+// applicationsServiceMock.getAppsForSuperAdminAndAccountAdmin.and.returnValue(deferredAdminApps.promise);
+//
+// }));
+//
+// beforeEach(()=> {
+// errorMessageByCode = [];
+// ECOMP_URL_REGEX = "";
+// scope = $rootScope.$new();
+// createController(scope);
+// });
+//
+// let createController = scopeObj => {
+// widgetDetails = $controller('WidgetDetailsModalCtrl', {
+// $scope: scope,
+// $log: $log,
+// applicationsService: applicationsServiceMock,
+// widgetsService: widgetsServiceMock,
+// errorMessageByCode: errorMessageByCode,
+// ECOMP_URL_REGEX: ECOMP_URL_REGEX,
+// userProfileService: userProfileServiceMock
+// });
+// };
+//
+// /**
+// * MOCK DATA
+// */
+// let newWidgetModel = {
+// name: null,
+// appId: null,
+// appName: null,
+// width: 360,
+// height: 300,
+// url: null
+// };
+// let exsistingWidget = {
+// name: 'some widget',
+// appId: 1,
+// appName: 'APP NAME',
+// width: 360,
+// height: 300,
+// url: 'http://a.com'
+// };
+// let adminApps = [{id: 1, name: 'a'}, {id: 2, name: 'b'}];
+//
+// /**
+// * TEST CASES
+// */
+// it('should initialize controller with new widget mode when opening the modal without selected widget', ()=> {
+// expect(widgetDetails.widget).toEqual(newWidgetModel);
+// });
+//
+// it('should initialize controller with exsisting widget details when opening the modal with selected widget', ()=> {
+// scope.ngDialogData = {
+// widget: exsistingWidget
+// };
+// createController(scope);
+// expect(widgetDetails.widget).toEqual(exsistingWidget);
+// });
+//
+// it('should populate widget selected app name and id when initializing controller with widget', () =>{
+// deferredAdminApps.resolve(adminApps);
+// scope.ngDialogData = {
+// widget: exsistingWidget
+// };
+// createController(scope);
+// scope.$apply();
+// expect(widgetDetails.widget.appId).toEqual(adminApps[0].id);
+// expect(widgetDetails.widget.appName).toEqual(adminApps[0].name);
+// });
+//
+// //TODO:
+// //save changes fail - conflict handling
+// //save changes success
+//
+//
+//
+// });
diff --git a/ecomp-portal-FE-common/client/app/views/widget-onboarding/widget-details-dialog/widget-details.modal.html b/ecomp-portal-FE-common/client/app/views/widget-onboarding/widget-details-dialog/widget-details.modal.html
new file mode 100644
index 00000000..2fa56443
--- /dev/null
+++ b/ecomp-portal-FE-common/client/app/views/widget-onboarding/widget-details-dialog/widget-details.modal.html
@@ -0,0 +1,156 @@
+<!--
+ ================================================================================
+ 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="widget-details-modal">
+ <div id="'widgets-details-title" class="title">Widget Details</div>
+
+ <div class="widget-properties-main"
+ scroll-top="widgetOnboardingDetails.scrollApi">
+ <form id="widgets-details-form" name="widgetForm" novalidate
+ autocomplete="off">
+
+ <div class="item required">
+ <div class="item-label">Widget Name</div>
+ <input id="widgets-details-input-name" class="input-field"
+ type="text" ng-model="widgetOnboardingDetails.widget.name"
+ ng-change="widgetOnboardingDetails.updateWidgetName()" name="name"
+ ng-pattern="/^[\w -]*$/" maxlength="100"
+ ng-disabled="widgetOnboardingDetails.isEditMode" required />
+
+ <div class="error-container"
+ ng-show="(widgetOnboardingDetails.emptyWidgetName || widgetForm.name.$dirty) && !widgetOnboardingDetails.duplicatedName">
+ <div id="widgets-details-input-name-conflict" class="err-message">Name
+ not available - choose different name</div>
+ </div>
+
+ <div class="error-container"
+ ng-show="(widgetOnboardingDetails.emptyWidgetName || widgetForm.name.$dirty) && widgetOnboardingDetails.duplicatedName">
+ <div ng-messages="widgetForm.name.$error" class="error-container">
+ <small id="widgets-details-input-name-required"
+ class="err-message" ng-message="required">Widget Name is
+ required</small> <small id="widgets-details-input-name-pattern"
+ class="err-message" ng-message="pattern">Widget Name must
+ be letters, numbers, or underscore</small>
+ </div>
+ </div>
+ </div>
+
+
+ <div class="item">
+ <div class="item-label">Widget Description</div>
+ <input id="widgets-details-input-name" class="input-field"
+ type="text" ng-model="widgetOnboardingDetails.widget.desc"
+ name="desc" maxlength="200" />
+ </div>
+
+ <div class="widget-property">
+ <input id="widgets-checkbox-app-is-enabled" type="checkbox"
+ class="checkbox-field"
+ ng-model="widgetOnboardingDetails.widget.allUser" />
+ <div class="property-label checkbox-label">Allow all user
+ access</div>
+ </div>
+
+
+ <div class="item" ng-show="!widgetOnboardingDetails.isEditMode">
+ <div class="item-label">Service Endpoint</div>
+ <div>
+ <select id="widgets-details-input-endpoint-url" name="url"
+ class="input-field"
+ ng-model="widgetOnboardingDetails.widget.serviceURL"
+ ng-options="service as service.option
+ for service in widgetOnboardingDetails.availableServices">
+ <option value="" selected="selected">Select Microservice
+ Endpoint</option>
+ </select>
+ </div>
+ </div>
+
+ <div class="item required"
+ ng-show="!widgetOnboardingDetails.widget.allUser">
+ <div class="item-label">Application Name</div>
+ <div>
+ <multiple-select id="widget-applications" unique-data="{{$index}}"
+ placeholder="Select Applications"
+ ng-model="widgetOnboardingDetails.availableApps"
+ on-change="widgetOnboardingDetails.appUpdate()" name-attr="name"
+ value-attr="isSelected"> </multiple-select>
+ </div>
+ <div class="error-container"
+ ng-show="widgetOnboardingDetails.appCounter == 0">
+ <div id="widgets-details-input-name-conflict" class="err-message">Please
+ select at least one Application</div>
+ </div>
+ </div>
+
+ <div class="item" ng-show="!widgetOnboardingDetails.widget.allUser">
+ <div ng-show="widgetOnboardingDetails.hasSelectedApp"
+ class="item-label">User Role Name</div>
+ <div ng-repeat="appRoles in widgetOnboardingDetails.availableApps"
+ id="roles-{{appRoles.roles.split(' ').join('-')}}">
+ <div class="item required">
+ <div class="app-item-left" ng-show="appRoles.isSelected">{{appRoles.name}}</div>
+ <div class="app-item-right" ng-show="appRoles.isSelected">
+ <multiple-select id="widget-roles-by-application"
+ unique-data="{{$index}}" placeholder="Select Roles"
+ ng-model="appRoles.roles" name-attr="name"
+ on-change="widgetOnboardingDetails.roleUpdate(appRoles)"
+ value-attr="isSelected"></multiple-select>
+ <div class="error-container" ng-show="!appRoles.roleSelected">
+ <div id="widgets-details-input-name-conflict"
+ class="err-message">Please select at least one role</div>
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+
+ <div class="item required">
+ <div class="item-label">Upload Widget</div>
+ <div>
+ <input id="widget-onboarding-details-upload-file"
+ file-model="widgetOnboardingDetails.widget.file" type="file"
+ style="height: 24px;" />
+
+
+ <div class="error-container"
+ ng-show="widgetOnboardingDetails.widget.file == undefined && !widgetOnboardingDetails.isEditMode">
+ <div class="err-message">Please upload your widget (.zip)</div>
+ </div>
+ </div>
+ </div>
+ </form>
+ </div>
+
+ <div class="dialog-control">
+ <span class="ecomp-save-spinner"
+ ng-show="widgetOnboardingDetails.isSaving"></span>
+ <button id="widgets-details-save-button" class="btn btn-alt btn-small"
+ ng-class="{disabled: widgetOnboardingDetails.widget.name == undefined || !widgetOnboardingDetails.duplicatedName
+ || (!widgetOnboardingDetails.widget.allUser && widgetOnboardingDetails.appCounter == 0) || (widgetOnboardingDetails.widget.file == undefined && !widgetOnboardingDetails.isEditMode)
+ || (!widgetOnboardingDetails.widget.allUser && !widgetOnboardingDetails.allRoleSelected) || (widgetOnboardingDetails.widget.saving)}"
+ ng-click="widgetOnboardingDetails.saveChanges()">Save</button>
+ <button id="widgets-details-cancel-button"
+ class="btn btn-alt btn-small" ng-click="closeThisDialog()">Cancel</button>
+
+ </div>
+
+
+
+</div>
diff --git a/ecomp-portal-FE-common/client/app/views/widget-onboarding/widget-details-dialog/widget-details.modal.less b/ecomp-portal-FE-common/client/app/views/widget-onboarding/widget-details-dialog/widget-details.modal.less
new file mode 100644
index 00000000..d7cf2671
--- /dev/null
+++ b/ecomp-portal-FE-common/client/app/views/widget-onboarding/widget-details-dialog/widget-details.modal.less
@@ -0,0 +1,102 @@
+.widget-details-modal {
+ height: 580px;
+ .title {
+ //.n18r;
+ .dGray18r; //AT&T Dark Gray
+ border-bottom: @portalDBlue 3px solid;
+ }
+ .widget-input-field{
+ width:250px;
+ }
+ .widget-properties-main {
+ padding: 16px;
+ height: 460px;
+ overflow-y: auto;
+
+ .widget-property{
+ position: relative;
+ margin-bottom: 18px;
+ .property-label{
+ .dGray14r;
+ }
+ .checkbox-label{
+ display: inline-block;
+ padding-left: 3px;
+ }
+ .checkbox-field{
+ padding: 0;
+ margin: 0;
+ vertical-align: middle;
+ position: relative;
+ top: -1px;
+ height:15px;
+ }
+
+ }
+ .widget-upload-field{
+ height:24px;
+ border: 0px solid #d2d2d2;
+ box-shadow: 0px 0px 2px -2px rgba(0, 0, 0, 0.08) inset;
+ padding-left: 2px;
+ }
+ .item{
+ position: relative;
+ margin-bottom: 18px;
+
+ .input-field{
+ .custom-input-field;
+ width: 100%;
+ &.url{
+ width: 78%;
+ display: inline-block;
+ }
+ }
+
+ .select-field {
+ .custom-select-field;
+ }
+
+ .item-label{
+ .dGray14r;
+ }
+
+ .right-item{
+ position: relative;
+ display: inline-block;
+ width: 48%;
+ float: right;
+ }
+ .left-item{
+ display: inline-block;
+ width: 48%;
+ }
+
+ .url-validation-button{
+ .btn-blue;
+ width: 20%;
+ display: inline-block;
+ float: right;
+ }
+
+ .error-container{
+ position: absolute;
+ width: 280px;
+ display: block;
+ height: 12px;
+ line-height: 12px;
+
+ .err-message{
+ color: @funcRed;
+ font-size: 9px;
+ }
+ .valid-message{
+ color: @funcGreen;
+ font-size: 9px;
+ }
+ }
+
+ }
+
+ }
+
+}