From 627badaf69987c01811c477219fd943757a635f5 Mon Sep 17 00:00:00 2001 From: "Christopher Lott (Christopher) (cl778h)" Date: Mon, 12 Jun 2017 09:49:00 -0400 Subject: [PORTAL-16 PORTAL-18] Widget ms; staging Remove staging repositories from poms. Add widget microservice code base. Add portal unit tests. Repair defects. Normalize line endings. Change-Id: Ia5e48da2a3141b352439ecd548cddf918f4df585 Signed-off-by: Christopher Lott (cl778h) --- .../views/dashboard/dashboard-widget-manage.html | 305 ++-- .../dashboard-widget-parameter-manage.html | 178 +- .../dashboard-widget-parameters.controller.js | 162 +- .../dashboard-widget-parameters.controller.less | 54 +- .../views/dashboard/dashboard-widget.controller.js | 844 ++++----- .../app/views/dashboard/dashboard.controller.js | 1029 +++++------ .../client/app/views/dashboard/dashboard.less | 1809 ++++++++++---------- .../client/app/views/dashboard/dashboard.tpl.html | 362 ++-- 8 files changed, 2392 insertions(+), 2351 deletions(-) (limited to 'ecomp-portal-FE-common/client/app/views/dashboard') diff --git a/ecomp-portal-FE-common/client/app/views/dashboard/dashboard-widget-manage.html b/ecomp-portal-FE-common/client/app/views/dashboard/dashboard-widget-manage.html index 9883bd14..f47e17c2 100644 --- a/ecomp-portal-FE-common/client/app/views/dashboard/dashboard-widget-manage.html +++ b/ecomp-portal-FE-common/client/app/views/dashboard/dashboard-widget-manage.html @@ -1,152 +1,153 @@ - -
-

-
-
- -
-
Manage {{widgetTypeDisplay}} Widgets
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - -
TitleURLDateContentOrderEditDelete
-
- -
-
- -
-
- -
-
{{rowData.content | cut:true:20:' ...'}}
- -
-
- -
-
- -
- - Save - -
-
- -
-
-
- -
-
-
-
-

Add

-
{{errMsg}}
-
-
-
-
-
-
-
Title
- -
-
-
URL
- -
-
-
Sort Order
- -
-
-
-

Event Date

-
-
-

- -

-
-
-
- -
-
Content
- -
-
-
- Add New - -
- -
- -
-
-
-
- Close -
-
-
-
-
- - + +
+

+
+
+ +
+
Manage {{widgetTypeDisplay}} Widgets
+
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
TitleURLDateContentOrderEditDelete
+
+ +
+
+ +
+
+ +
+
{{rowData.content | cut:true:20:' ...'}}
+ +
+
+ +
+
+ +
+ + Save + +
+
+ +
+
+
+ +
+
+
+
+

Add

+
{{errMsg}}
+
+
+
+
+
+
+
Title
+ +
+
+
URL
+ +
+
+
Sort Order
+ +
+
+
+

Event Date

+
+
+

+ +

+
+
+
+ +
+
Content
+ +
+
+
+ Add New + +
+ +
+ +
+
+
+
+ Close +
+
+
+
+
+ + diff --git a/ecomp-portal-FE-common/client/app/views/dashboard/dashboard-widget-parameter-manage.html b/ecomp-portal-FE-common/client/app/views/dashboard/dashboard-widget-parameter-manage.html index 59e6f4fa..1f958b7f 100644 --- a/ecomp-portal-FE-common/client/app/views/dashboard/dashboard-widget-parameter-manage.html +++ b/ecomp-portal-FE-common/client/app/views/dashboard/dashboard-widget-parameter-manage.html @@ -1,86 +1,92 @@ - -
-
Manage - Widgets Parameters Page
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - -
Parameter - KeyMy ValueDefault ValueEditReset to Default
-
-
-
- -
-
-
-
- -
Save - -
-
- -
- -
-
- There is no parameter assoicated with this widget! -
- -
- -
-
-
+ +
+
Manage + Widgets Parameters Page
+
+
+
+
+ + + + + + + + + + + + + + + + + + + + + +
Parameter + KeyMy ValueDefault ValueEditReset to Default
+
+
+
+ +
+
+
+
+ +
Save + +
+
+ +
+ +
+
+ There is no parameter assoicated with this widget! +
+ +
+ +
+
+
+ + diff --git a/ecomp-portal-FE-common/client/app/views/dashboard/dashboard-widget-parameters.controller.js b/ecomp-portal-FE-common/client/app/views/dashboard/dashboard-widget-parameters.controller.js index 460618ea..fb9a254f 100644 --- a/ecomp-portal-FE-common/client/app/views/dashboard/dashboard-widget-parameters.controller.js +++ b/ecomp-portal-FE-common/client/app/views/dashboard/dashboard-widget-parameters.controller.js @@ -1,81 +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. - * ================================================================================ - */ -'use strict'; - -(function () { - class WidgetParameterController { - constructor($scope, widgetsCatalogService, userProfileService) { - let widgetId = $scope.ngDialogData.widgetId; - $scope.modflag = false; - $scope.isLoadingTable = false; - $scope.messageInfo = false; - - widgetsCatalogService.getWidgetCatalogParameters(widgetId).then(res => { - if(res.status == 'OK'){ - $scope.isLoadingTable = true; - $scope.widgetParam = res.response; - }else if(res.status == 'WARN'){ - $scope.messageInfo = true; - } - }).catch(err => { - $log.error('WidgetParameterController::init error: ' + err); - }) - - $scope.setEdit = function(index) { - if($scope.modflag === false){ - $scope.widgetParam[index].showEdit = true; - $scope.modflag = true; - } - } - - $scope.resetDefault = function(index) { - var widgetParamObject = {}; - widgetParamObject.user_value = $scope.widgetParam[parseInt(index)].default_value; - widgetParamObject.paramId = $scope.widgetParam[parseInt(index)].param_id; - widgetParamObject.widgetId = widgetId; - widgetsCatalogService.saveWidgetParameter(widgetParamObject) - .then(function(res){ - if(res.status == 'OK'){ - $scope.widgetParam[index].user_value = $scope.widgetParam[index].default_value; - } - }); - } - - $scope.modify = function(index) { - - var widgetParamObject = {}; - widgetParamObject.user_value = $scope.widgetParam[parseInt(index)].user_value; - widgetParamObject.paramId = $scope.widgetParam[parseInt(index)].param_id; - widgetParamObject.widgetId = widgetId; - - widgetsCatalogService.saveWidgetParameter(widgetParamObject) - .then(function(res){ - if(res.status == 'OK'){ - $scope.modflag = false; - $scope.widgetParam[index].showEdit = false; - } - }); - - }; - } - } - WidgetParameterController.$inject = ['$scope', 'widgetsCatalogService', 'userProfileService']; - angular.module('ecompApp').controller('WidgetParameterController', WidgetParameterController); -})(); +/*- + * ================================================================================ + * 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 WidgetParameterController { + constructor($scope, widgetsCatalogService, userProfileService) { + let widgetId = $scope.ngDialogData.widgetId; + $scope.modflag = false; + $scope.isLoadingTable = false; + $scope.messageInfo = false; + + widgetsCatalogService.getWidgetCatalogParameters(widgetId).then(res => { + if(res.status == 'OK'){ + $scope.isLoadingTable = true; + $scope.widgetParam = res.response; + }else if(res.status == 'WARN'){ + $scope.messageInfo = true; + } + }).catch(err => { + $log.error('WidgetParameterController::init error: ' + err); + }) + + $scope.setEdit = function(index) { + if($scope.modflag === false){ + $scope.widgetParam[index].showEdit = true; + $scope.modflag = true; + } + } + + $scope.resetDefault = function(index) { + var widgetParamObject = {}; + widgetParamObject.user_value = $scope.widgetParam[parseInt(index)].default_value; + widgetParamObject.paramId = $scope.widgetParam[parseInt(index)].param_id; + widgetParamObject.widgetId = widgetId; + widgetsCatalogService.saveWidgetParameter(widgetParamObject) + .then(function(res){ + if(res.status == 'OK'){ + $scope.widgetParam[index].user_value = $scope.widgetParam[index].default_value; + } + }); + } + + $scope.modify = function(index) { + + var widgetParamObject = {}; + widgetParamObject.user_value = $scope.widgetParam[parseInt(index)].user_value; + widgetParamObject.paramId = $scope.widgetParam[parseInt(index)].param_id; + widgetParamObject.widgetId = widgetId; + + widgetsCatalogService.saveWidgetParameter(widgetParamObject) + .then(function(res){ + if(res.status == 'OK'){ + $scope.modflag = false; + $scope.widgetParam[index].showEdit = false; + } + }); + + }; + } + } + WidgetParameterController.$inject = ['$scope', 'widgetsCatalogService', 'userProfileService']; + angular.module('ecompApp').controller('WidgetParameterController', WidgetParameterController); +})(); diff --git a/ecomp-portal-FE-common/client/app/views/dashboard/dashboard-widget-parameters.controller.less b/ecomp-portal-FE-common/client/app/views/dashboard/dashboard-widget-parameters.controller.less index ce63acd4..76521f9b 100644 --- a/ecomp-portal-FE-common/client/app/views/dashboard/dashboard-widget-parameters.controller.less +++ b/ecomp-portal-FE-common/client/app/views/dashboard/dashboard-widget-parameters.controller.less @@ -1,28 +1,28 @@ -.manage-widget-parameters-title{ - color: #067ab4; - font-family: "Omnes-ECOMP-W02", Arial;; - font-size: 24px; - margin-left: 30px; - width: 1170px; - margin-top: 20px; - margin-bottom: 10px; -} - -.manage-widget-parameters-table{ - margin: 30px; -} - -.manage-widget-parameters-table-details{ - height: 300px; - background-color: #ffffff; -} - -.manage-widget-parameters-header{ - margin-top: 20px; - margin-bottom: 20px; - height:20px; -} - -.ngdialog-content{ - width: 40%; +.manage-widget-parameters-title{ + color: #067ab4; + font-family: "Omnes-ECOMP-W02", Arial;; + font-size: 24px; + margin-left: 30px; + width: 1170px; + margin-top: 20px; + margin-bottom: 10px; +} + +.manage-widget-parameters-table{ + margin: 30px; +} + +.manage-widget-parameters-table-details{ + height: 300px; + background-color: #ffffff; +} + +.manage-widget-parameters-header{ + margin-top: 20px; + margin-bottom: 20px; + height:20px; +} + +.ngdialog-content{ + width: 40%; } \ No newline at end of file diff --git a/ecomp-portal-FE-common/client/app/views/dashboard/dashboard-widget.controller.js b/ecomp-portal-FE-common/client/app/views/dashboard/dashboard-widget.controller.js index fe0bf453..aff4e0c1 100644 --- a/ecomp-portal-FE-common/client/app/views/dashboard/dashboard-widget.controller.js +++ b/ecomp-portal-FE-common/client/app/views/dashboard/dashboard-widget.controller.js @@ -1,422 +1,422 @@ -/*- - * ================================================================================ - * 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 CommonWidgetController { - constructor(dashboardService, $scope, message, $q, $http, conf, $filter,confirmBoxService,$log) { - $scope.widgetType = message.type; - $scope.widgetTypeDisplay = message.type; - $scope.modflag = false; - - switch (message.type) { - case 'EVENTS': - $scope.widgetTypeDisplay = 'Events' - break; - case 'NEWS': - $scope.widgetTypeDisplay = 'News' - break; - case 'IMPORTANTRESOURCES': - $scope.widgetTypeDisplay = 'Resources' - break; - } - - $scope.widgetData = []; - dashboardService.getCommonWidgetData(message.type) - .then(function (res) { - // console.log('CommonWidgetController: result is ' + res); - $scope.widgetData = res.response.items; - }); - - - - $scope.setEdit = function(index) { - - //for(var i=0; i<$scope.widgetData ) - - if($scope.modflag === false){ - $scope.widgetData[index].showEdit = true; - $scope.modflag = true; - } - } - - $scope.modify = function(index) { - - $scope.widgetObject = {}; - $scope.widgetObject.id = $scope.widgetData[parseInt(index)].id; - $scope.widgetObject.category = $scope.widgetData[parseInt(index)].category; - $scope.widgetObject.title = $scope.widgetData[parseInt(index)].title; - $scope.widgetObject.href = $scope.widgetData[parseInt(index)].href; - $scope.widgetObject.eventDate = $scope.widgetData[parseInt(index)].eventDate; - $scope.widgetObject.content = $scope.widgetData[parseInt(index)].content; - $scope.widgetObject.sortOrder = $scope.widgetData[parseInt(index)].sortOrder; - - var validateMsg = $scope.validateWidgetObject($scope.widgetObject); - if (validateMsg) { - confirmBoxService.showInformation(validateMsg).then(isConfirmed => {return;}); - return; - } - - dashboardService.saveCommonWidgetData($scope.widgetObject) - .then(function(res){ - if (res.status == 'OK') { - dashboardService.getCommonWidgetData(message.type) - .then(function(res){ - $scope.widgetData = res.response.items; - $scope.modflag = false; - $scope.cancelEdit(index); - }); - } - else { - // Save failed - confirmBoxService.showInformation("Save failed").then(isConfirmed => {return;}); - return; - } - }); - - }; - - $scope.newWidgetObject = {}; - - // Answers string error if validation fails; - // answers null if all is well. - $scope.validateWidgetObject = function(wo) { - if (wo.title == null || wo.title == '') - return "Please enter a title."; - if (wo.href == null || wo.href == '' || !validateUrl(wo.href)) - return "Please enter a valid URL that starts with http."; - if (wo.sortOrder == null || wo.sortOrder == '' || isNaN(parseInt(wo.sortOrder))) - return "Please enter a number for the sort order."; - if (wo.category=='EVENTS') { - if (wo.eventDate == null || wo.eventDate == '') - return "Please enter a date for the event."; - // Parses and normalizes the date with rollover. - var filteredDate = $filter('date')(wo.eventDate, "yyyy-MM-dd"); - // $log.debug('dashboard-widget-controller: date filter yields ' + filteredDate); - // The date picker shows mm/dd/yy. - if (filteredDate == null || filteredDate.length != 10) - return "Please enter a valid date as YYYY-MM-DD"; - if (wo.content==null || wo.content=='') - return "Please enter content for the event."; - } - return null; - }; - - $scope.saveNew = function() { - $scope.newWidgetObject.category = message.type; - // $log.info($scope.newWidgetObject); - var validateMsg = $scope.validateWidgetObject($scope.newWidgetObject); - if (validateMsg) { - confirmBoxService.showInformation(validateMsg).then(isConfirmed => {return;}); - return; - } - // Transform date into expected storage format - $scope.newWidgetObject.eventDate = $filter('date')($scope.newWidgetObject.eventDate, "yyyy-MM-dd"); - - dashboardService.saveCommonWidgetData($scope.newWidgetObject) - .then(function(res){ - if (res.status == 'OK') { - $scope.widgetForm.$setPristine(); - confirmBoxService.showInformation('You have added a new item').then(isConfirmed => { - }); - dashboardService.getCommonWidgetData(message.type) - .then(function(res){ - $scope.widgetData = res.response.items; - $scope.newWidgetObject = {}; - }); - } - else { - confirmBoxService.showInformation("Save failed").then(isConfirmed => {return;}); - return; - } - }); - }; - - $scope.remove = function(index) { - var confirmMsg = 'Are you sure you want to delete this item from the list?' + ' Press OK to delete.'; - confirmBoxService.confirm(confirmMsg).then(function (confirmed) { - if (confirmed == true) { - $scope.widgetObject = {}; - $scope.widgetObject.id = $scope.widgetData[parseInt(index)].id; - $scope.widgetObject.category = $scope.widgetData[parseInt(index)].category; - $scope.widgetObject.title = $scope.widgetData[parseInt(index)].title; - $scope.widgetObject.href = $scope.widgetData[parseInt(index)].href; - $scope.widgetObject.sortOrder = $scope.widgetData[parseInt(index)].sortOrder; - - - dashboardService.removeCommonWidgetData($scope.widgetObject) - .then(function(res){ - dashboardService.getCommonWidgetData(message.type) - .then(function(res){ - $scope.widgetData = res.response.items; - $scope.cancelEdit(index); - }); - }); - } - }); - - }; - $scope.closeDialog = function(){ - $scope.closeThisDialog( $scope.widgetData); - } - $scope.deleteSpeedDial = function(widget){ - - } - - $scope.manage = function(index) { - $scope.modflag = true; - - var thisdata = $scope.widgetData[index]; - $scope.editMode=true; - var category = "#category"+index; - var categoryEdit = "#categoryEdit"+index; - - var title = "#title"+index; - var titleEdit = "#titleEdit"+index; - - var url = "#href"+index; - var urlEdit = "#hrefEdit"+index; - - var order = "#order"+index; - var orderEdit = "#orderEdit"+index; - - var eventDate = "#eventDate"+index; - var eventDateEdit = "#eventDateEdit"+index; - - - var dsavebutton ="#savebutton"+index; - var dremovebutton="#removebutton"+index; - var dmanagebutton="#managebutton"+index; - var deditRbutton="#editRbutton"+index; - - $(title).css('display', 'none'); - $(titleEdit).css('display', 'inherit'); - $(url).css('display', 'none'); - $(urlEdit).css('display', 'inherit'); - $(order).css('display', 'none'); - $(orderEdit).css('display', 'inherit'); - $(eventDate).css('display', 'none'); - $(eventDateEdit).css('display', 'inherit'); - - $(dsavebutton).css('display', 'inherit'); - $(dremovebutton).css('display', 'inherit'); - $(dmanagebutton).css('display', 'none'); - $(deditRbutton).css('display', 'inherit'); - - }; - - $scope.cancelEdit = function(index) { - - $scope.editMode=false; - var category = "#category"+index; - var categoryEdit = "#categoryEdit"+index; - - var title = "#title"+index; - var titleEdit = "#titleEdit"+index; - - var url = "#href"+index; - var urlEdit = "#hrefEdit"+index; - - var order = "#order"+index; - var orderEdit = "#orderEdit"+index; - - var eventDate = "#eventDate"+index; - var eventDateEdit = "#eventDateEdit"+index; - - var dsavebutton ="#savebutton"+index; - var dremovebutton ="#removebutton"+index; - var dmanagebutton="#managebutton"+index; - var deditRbutton="#editRbutton"+index; - - $(title).css('display', 'inherit'); - $(titleEdit).css('display', 'none'); - - $(url).css('display', 'inherit'); - $(urlEdit).css('display', 'none'); - - $(order).css('display', 'inherit'); - $(orderEdit).css('display', 'none'); - - $(eventDate).css('display', 'inherit'); - $(eventDateEdit).css('display', 'none'); - - $(dsavebutton).css('display', 'none'); - $(dremovebutton).css('display', 'none'); - $(dmanagebutton).css('display', 'inherit'); - $(deditRbutton).css('display', 'none'); - - }; - - $scope.popupConfirmWin = function(title, msgBody, callback){ - modalService.popupConfirmWin.apply(null, arguments); - }; - } - } - CommonWidgetController.$inject = ['dashboardService', '$scope', 'message', '$q', '$http', 'conf', '$filter','confirmBoxService','$log']; - angular.module('ecompApp').controller('CommonWidgetController', CommonWidgetController); -})(); - -angular.module('ecompApp').filter('cut', function () { - return function (value, wordwise, max, tail) { - if (!value) return ''; - - max = parseInt(max, 10); - if (!max) return value; - if (value.length <= max) return value; - - value = value.substr(0, max); - if (wordwise) { - var lastspace = value.lastIndexOf(' '); - if (lastspace != -1) { - //Also remove . and , so its gives a cleaner result. - if (value.charAt(lastspace-1) == '.' || value.charAt(lastspace-1) == ',') { - lastspace = lastspace - 1; - } - value = value.substr(0, lastspace); - } - } - - return value + (tail || ' …'); - }; -}); - -angular.module('ecompApp').controller('DatePickerController', function ($scope, uibDateParser) { - $scope.today = function() { - $scope.dt = new Date(); - }; - $scope.today(); - - $scope.clear = function() { - $scope.dt = null; - }; - - $scope.inlineOptions = { - customClass: getDayClass, - minDate: new Date(), - showWeeks: true - }; - - $scope.dateOptions = { - dateDisabled: disabled, - formatYear: 'yy', - minDate: new Date(), - startingDay: 1 - }; - - // Disable weekend selection - function disabled(data) { - var date = data.date, - mode = data.mode; - return mode === 'day' && (date.getDay() === 0 || date.getDay() === 6); - } - - $scope.toggleMin = function() { - $scope.inlineOptions.minDate = $scope.inlineOptions.minDate ? null : new Date(); - $scope.dateOptions.minDate = $scope.inlineOptions.minDate; - }; - - $scope.toggleMin(); - - $scope.open1 = function() { - // console.log('In open1'); - $scope.popup1.opened = true; - }; - - $scope.open2 = function() { - // console.log('In open2'); - $scope.popup2.opened = true; - }; - - - $scope.setDate = function(year, month, day) { - $scope.dt = new Date(year, month, day); - }; - - $scope.formats = ['dd-MMMM-yyyy', 'yyyy/MM/dd', 'dd.MM.yyyy', 'shortDate']; - $scope.format = $scope.formats[3]; - $scope.altInputFormats = ['M!/d!/yyyy']; - - $scope.popup1 = { - opened: false - }; - - $scope.popup2 = { - opened: false - }; - - var tomorrow = new Date(); - tomorrow.setDate(tomorrow.getDate() + 1); - var afterTomorrow = new Date(); - afterTomorrow.setDate(tomorrow.getDate() + 1); - $scope.events = [ - { - date: tomorrow, - status: 'full' - }, - { - date: afterTomorrow, - status: 'partially' - } - ]; - - function getDayClass(data) { - var date = data.date, - mode = data.mode; - if (mode === 'day') { - var dayToCheck = new Date(date).setHours(0,0,0,0); - - for (var i = 0; i < $scope.events.length; i++) { - var currentDay = new Date($scope.events[i].date).setHours(0,0,0,0); - - if (dayToCheck === currentDay) { - return $scope.events[i].status; - } - } - } - - return ''; - } -}); - - - -function toggleCollapsible(id, clickedIconId, subtitutingIconId){ - $("#"+id).toggle(); - $("#"+clickedIconId).toggle(); - $("#"+subtitutingIconId).toggle(); - setTimeout(function(){focusFirstEle(id);}, 1000); -} - -function focusFirstEle(id){ - var focusItems = $("#"+id).find(":focusable"); - for(var i=0; i {return;}); + return; + } + + dashboardService.saveCommonWidgetData($scope.widgetObject) + .then(function(res){ + if (res.status == 'OK') { + dashboardService.getCommonWidgetData(message.type) + .then(function(res){ + $scope.widgetData = res.response.items; + $scope.modflag = false; + $scope.cancelEdit(index); + }); + } + else { + // Save failed + confirmBoxService.showInformation("Save failed").then(isConfirmed => {return;}); + return; + } + }); + + }; + + $scope.newWidgetObject = {}; + + // Answers string error if validation fails; + // answers null if all is well. + $scope.validateWidgetObject = function(wo) { + if (wo.title == null || wo.title == '') + return "Please enter a title."; + if (wo.href == null || wo.href == '' || !validateUrl(wo.href)) + return "Please enter a valid URL that starts with http."; + if (wo.sortOrder == null || wo.sortOrder == '' || isNaN(parseInt(wo.sortOrder))) + return "Please enter a number for the sort order."; + if (wo.category=='EVENTS') { + if (wo.eventDate == null || wo.eventDate == '') + return "Please enter a date for the event."; + // Parses and normalizes the date with rollover. + var filteredDate = $filter('date')(wo.eventDate, "yyyy-MM-dd"); + // $log.debug('dashboard-widget-controller: date filter yields ' + filteredDate); + // The date picker shows mm/dd/yy. + if (filteredDate == null || filteredDate.length != 10) + return "Please enter a valid date as YYYY-MM-DD"; + if (wo.content==null || wo.content=='') + return "Please enter content for the event."; + } + return null; + }; + + $scope.saveNew = function() { + $scope.newWidgetObject.category = message.type; + // $log.info($scope.newWidgetObject); + var validateMsg = $scope.validateWidgetObject($scope.newWidgetObject); + if (validateMsg) { + confirmBoxService.showInformation(validateMsg).then(isConfirmed => {return;}); + return; + } + // Transform date into expected storage format + $scope.newWidgetObject.eventDate = $filter('date')($scope.newWidgetObject.eventDate, "yyyy-MM-dd"); + + dashboardService.saveCommonWidgetData($scope.newWidgetObject) + .then(function(res){ + if (res.status == 'OK') { + $scope.widgetForm.$setPristine(); + confirmBoxService.showInformation('You have added a new item').then(isConfirmed => { + }); + dashboardService.getCommonWidgetData(message.type) + .then(function(res){ + $scope.widgetData = res.response.items; + $scope.newWidgetObject = {}; + }); + } + else { + confirmBoxService.showInformation("Save failed").then(isConfirmed => {return;}); + return; + } + }); + }; + + $scope.remove = function(index) { + var confirmMsg = 'Are you sure you want to delete this item from the list?' + ' Press OK to delete.'; + confirmBoxService.confirm(confirmMsg).then(function (confirmed) { + if (confirmed == true) { + $scope.widgetObject = {}; + $scope.widgetObject.id = $scope.widgetData[parseInt(index)].id; + $scope.widgetObject.category = $scope.widgetData[parseInt(index)].category; + $scope.widgetObject.title = $scope.widgetData[parseInt(index)].title; + $scope.widgetObject.href = $scope.widgetData[parseInt(index)].href; + $scope.widgetObject.sortOrder = $scope.widgetData[parseInt(index)].sortOrder; + + + dashboardService.removeCommonWidgetData($scope.widgetObject) + .then(function(res){ + dashboardService.getCommonWidgetData(message.type) + .then(function(res){ + $scope.widgetData = res.response.items; + $scope.cancelEdit(index); + }); + }); + } + }); + + }; + $scope.closeDialog = function(){ + $scope.closeThisDialog( $scope.widgetData); + } + $scope.deleteSpeedDial = function(widget){ + + } + + $scope.manage = function(index) { + $scope.modflag = true; + + var thisdata = $scope.widgetData[index]; + $scope.editMode=true; + var category = "#category"+index; + var categoryEdit = "#categoryEdit"+index; + + var title = "#title"+index; + var titleEdit = "#titleEdit"+index; + + var url = "#href"+index; + var urlEdit = "#hrefEdit"+index; + + var order = "#order"+index; + var orderEdit = "#orderEdit"+index; + + var eventDate = "#eventDate"+index; + var eventDateEdit = "#eventDateEdit"+index; + + + var dsavebutton ="#savebutton"+index; + var dremovebutton="#removebutton"+index; + var dmanagebutton="#managebutton"+index; + var deditRbutton="#editRbutton"+index; + + $(title).css('display', 'none'); + $(titleEdit).css('display', 'inherit'); + $(url).css('display', 'none'); + $(urlEdit).css('display', 'inherit'); + $(order).css('display', 'none'); + $(orderEdit).css('display', 'inherit'); + $(eventDate).css('display', 'none'); + $(eventDateEdit).css('display', 'inherit'); + + $(dsavebutton).css('display', 'inherit'); + $(dremovebutton).css('display', 'inherit'); + $(dmanagebutton).css('display', 'none'); + $(deditRbutton).css('display', 'inherit'); + + }; + + $scope.cancelEdit = function(index) { + + $scope.editMode=false; + var category = "#category"+index; + var categoryEdit = "#categoryEdit"+index; + + var title = "#title"+index; + var titleEdit = "#titleEdit"+index; + + var url = "#href"+index; + var urlEdit = "#hrefEdit"+index; + + var order = "#order"+index; + var orderEdit = "#orderEdit"+index; + + var eventDate = "#eventDate"+index; + var eventDateEdit = "#eventDateEdit"+index; + + var dsavebutton ="#savebutton"+index; + var dremovebutton ="#removebutton"+index; + var dmanagebutton="#managebutton"+index; + var deditRbutton="#editRbutton"+index; + + $(title).css('display', 'inherit'); + $(titleEdit).css('display', 'none'); + + $(url).css('display', 'inherit'); + $(urlEdit).css('display', 'none'); + + $(order).css('display', 'inherit'); + $(orderEdit).css('display', 'none'); + + $(eventDate).css('display', 'inherit'); + $(eventDateEdit).css('display', 'none'); + + $(dsavebutton).css('display', 'none'); + $(dremovebutton).css('display', 'none'); + $(dmanagebutton).css('display', 'inherit'); + $(deditRbutton).css('display', 'none'); + + }; + + $scope.popupConfirmWin = function(title, msgBody, callback){ + modalService.popupConfirmWin.apply(null, arguments); + }; + } + } + CommonWidgetController.$inject = ['dashboardService', '$scope', 'message', '$q', '$http', 'conf', '$filter','confirmBoxService','$log']; + angular.module('ecompApp').controller('CommonWidgetController', CommonWidgetController); +})(); + +angular.module('ecompApp').filter('cut', function () { + return function (value, wordwise, max, tail) { + if (!value) return ''; + + max = parseInt(max, 10); + if (!max) return value; + if (value.length <= max) return value; + + value = value.substr(0, max); + if (wordwise) { + var lastspace = value.lastIndexOf(' '); + if (lastspace != -1) { + //Also remove . and , so its gives a cleaner result. + if (value.charAt(lastspace-1) == '.' || value.charAt(lastspace-1) == ',') { + lastspace = lastspace - 1; + } + value = value.substr(0, lastspace); + } + } + + return value + (tail || ' …'); + }; +}); + +angular.module('ecompApp').controller('DatePickerController', function ($scope, uibDateParser) { + $scope.today = function() { + $scope.dt = new Date(); + }; + $scope.today(); + + $scope.clear = function() { + $scope.dt = null; + }; + + $scope.inlineOptions = { + customClass: getDayClass, + minDate: new Date(), + showWeeks: true + }; + + $scope.dateOptions = { + dateDisabled: disabled, + formatYear: 'yy', + minDate: new Date(), + startingDay: 1 + }; + + // Disable weekend selection + function disabled(data) { + var date = data.date, + mode = data.mode; + return mode === 'day' && (date.getDay() === 0 || date.getDay() === 6); + } + + $scope.toggleMin = function() { + $scope.inlineOptions.minDate = $scope.inlineOptions.minDate ? null : new Date(); + $scope.dateOptions.minDate = $scope.inlineOptions.minDate; + }; + + $scope.toggleMin(); + + $scope.open1 = function() { + // console.log('In open1'); + $scope.popup1.opened = true; + }; + + $scope.open2 = function() { + // console.log('In open2'); + $scope.popup2.opened = true; + }; + + + $scope.setDate = function(year, month, day) { + $scope.dt = new Date(year, month, day); + }; + + $scope.formats = ['dd-MMMM-yyyy', 'yyyy/MM/dd', 'dd.MM.yyyy', 'shortDate']; + $scope.format = $scope.formats[3]; + $scope.altInputFormats = ['M!/d!/yyyy']; + + $scope.popup1 = { + opened: false + }; + + $scope.popup2 = { + opened: false + }; + + var tomorrow = new Date(); + tomorrow.setDate(tomorrow.getDate() + 1); + var afterTomorrow = new Date(); + afterTomorrow.setDate(tomorrow.getDate() + 1); + $scope.events = [ + { + date: tomorrow, + status: 'full' + }, + { + date: afterTomorrow, + status: 'partially' + } + ]; + + function getDayClass(data) { + var date = data.date, + mode = data.mode; + if (mode === 'day') { + var dayToCheck = new Date(date).setHours(0,0,0,0); + + for (var i = 0; i < $scope.events.length; i++) { + var currentDay = new Date($scope.events[i].date).setHours(0,0,0,0); + + if (dayToCheck === currentDay) { + return $scope.events[i].status; + } + } + } + + return ''; + } +}); + + + +function toggleCollapsible(id, clickedIconId, subtitutingIconId){ + $("#"+id).toggle(); + $("#"+clickedIconId).toggle(); + $("#"+subtitutingIconId).toggle(); + setTimeout(function(){focusFirstEle(id);}, 1000); +} + +function focusFirstEle(id){ + var focusItems = $("#"+id).find(":focusable"); + for(var i=0; i { - if(resourceType=='NEWS'){ - $scope.updateNews(); - }else if(resourceType=='EVENTS'){ - $scope.updateEvents(); - }else if(resourceType=='IMPORTANTRESOURCES'){ - $scope.updateImportRes(); - } - }); - }; - - $scope.editWidgetParameters = function(widgetId) { - let data = { - widgetId: widgetId - } - ngDialog.open({ - templateUrl : 'app/views/dashboard/dashboard-widget-parameter-manage.html', - controller : 'WidgetParameterController', - data: data - }).closePromise.then(needUpdate => { - - }); - }; - - $scope.sort_options = [ - {index: 0, value: 'N', title: 'Name'}, - {index: 1, value: 'L', title: 'Last used'}, - {index: 2, value: 'F', title: 'Most used'}, - {index: 3, value: 'M', title: 'Manual'} - ]; - - $scope.selectedSortTypeChanged = function(userAppSortTypePref) { - $scope.appsViewData = []; - $scope.appsView = []; - - $scope.sort_type = userAppSortTypePref; - - applicationsService - .getAppsOrderBySortPref(userAppSortTypePref) - .then(function(res) { - _this.apps = res; - $scope.applyPresentationDetailsToApps(_this.apps); - }) - applicationsService - .saveAppsSortTypePreference($scope.selectedSortType) - .then(function(res) { - // Nothing to do - }) - - } - $scope.$watch('selectedSortType.value', (newVal, oldVal) => { - for(var i=0;i<$scope.sort_options.length;i++){ - if($scope.sort_options[i].value==newVal){ - $scope.selectedSortType=angular.copy($scope.sort_options[i]);; - } - } - }); - - $scope.restoreSortSelected = function(){ - confirmBoxService.confirm("Restore the default size and position of all widgets?").then( - function(confirmed){ - var checkConfirm = confirmed; - if(checkConfirm === true){ - applicationsService - .delWidgetsSortPref($scope.widgetsViewData).then(function(){ - $state.reload(); - }); - } - }); - /* if(confirm('Restore the default size and position of all widgets?') == true) - { - applicationsService - .delWidgetsSortPref($scope.widgetsViewData).then(function(){ - $state.reload(); - }) - }*/ - - } - - $scope.applyPresentationDetailsToApps = function(appsReturned) { - var rowNo = 0; - for (var i = 0; i < _this.apps.length; i++) { - $scope.appsView[i] = { - sizeX : 1, - sizeY : 1, - headerText : '', - subHeaderText : '', - imageLink : '', - order : '', - url : '', - appid: '', - }; - $scope.appsView[i].headerText = appsReturned[i].name; - $scope.appsView[i].subHeaderText = appsReturned[i].notes; - let imgLnk = ''; - if (appsReturned[i].imageUrl) - imgLnk = conf.api.appThumbnail.replace(':appId', appsReturned[i].id); - //$log.debug('DashboardCtlr::applyPresn: imgLink = ' + imgLnk); - $scope.appsView[i].imageLink = imgLnk; - $scope.appsView[i].order = appsReturned[i].order; - $scope.appsView[i].url = appsReturned[i].url; - $scope.appsView[i].restrictedApp = appsReturned[i].restrictedApp; - $scope.appsView[i].appid = appsReturned[i].id; - } - $scope.appsView[_this.apps.length] = { - addRemoveApps : true, - sizeX : 1, - sizeY : 1, - headerText : 'Add/Remove Applications', - subHeaderText : '', - imageLink : 'assets/images/cloud.png', - order : '', - restrictedApp : false, - url : '', - }; - if($scope.appsView.length>6){ - $(".dashboard-boarder").css({ - "height" : "400px" - }); - }else{ - $(".dashboard-boarder").css({ - "height" : "210px" - }); - } - - if ($scope.appsView != undefined - && $scope.appsView != null - && $scope.appsView.length > 0) { - $scope.appsViewData = $scope.appsView; - } - } - -$scope.widgetsView = []; - - $scope.applyPresentationDetailsToWidgets = function(widgetsReturned){ - var rowNo = 0; - for (var i = 0; i < widgetsReturned.length; i++) { - $scope.widgetsView[i] = { - sizeX : '', - sizeY :'', - headerText:'', - widgetText:'', - widgetIdentifier : '', - url : '', - widgetid: '', - attrb:'', - row:'', - col:'', - }; - $scope.widgetsView[i].widgetid = widgetsReturned[i].id; - $scope.widgetsView[i].headerText = widgetsReturned[i].headerName; - $scope.widgetsView[i].widgetText = widgetsReturned[i].name; - - if(widgetsReturned[i].headerName.toLowerCase() === 'news'){ - $scope.widgetsView[i].widgetIdentifier = 'NEWS'; - } - else - if(widgetsReturned[i].headerName.toLowerCase() === 'resources'){ - $scope.widgetsView[i].widgetIdentifier = 'IMPORTANTRESOURCES'; - } - else - if(widgetsReturned[i].headerName.toLowerCase() === 'events'){ - $scope.widgetsView[i].widgetIdentifier = 'EVENTS'; - } - - $scope.widgetsView[i].url = widgetsReturned[i].url; - $scope.widgetsView[i].attrb = widgetsReturned[i].attrs; - if(widgetsReturned[i].width === null){ - $scope.widgetsView[i].sizeX = 2; - }else{ - $scope.widgetsView[i].sizeX = widgetsReturned[i].width; - } - if(widgetsReturned[i].height === null){ - $scope.widgetsView[i].sizeY = 2; - }else{ - $scope.widgetsView[i].sizeY = widgetsReturned[i].height; - } - $scope.widgetsView[i].row = widgetsReturned[i].x; - $scope.widgetsView[i].col = widgetsReturned[i].y; - } - if ($scope.widgetsView != undefined - && $scope.widgetsView != null - && $scope.widgetsView.length > 0) { - $scope.widgetsViewData = $scope.widgetsView; - } - } - - applicationsService - .getUserAppsSortTypePreference().then(function(res) { - var resJson = {}; - resJson.value = res; - if (resJson.value==="N" || resJson.value==="") { - resJson.index = 0; - resJson.title = 'Name'; - }else if (resJson.value==="L") { - resJson.index = 1; - resJson.title = 'Last used'; - }else if(resJson.value==="F"){ - resJson.index = 2; - resJson.title = 'Most used'; - }else { - resJson.index = 3; - resJson.title = 'Manual'; - } - $scope.selectedSortType = resJson; - $scope.selectedSortTypeChanged(res); - - - }); - - $scope.widgetsList = []; - - let getUserWidgets = (loginName) => { - var conf = this.conf; - widgetsCatalogService.getUserWidgets(loginName).then(res => { - if(!(res instanceof Array)){ - this.isCommError = true; - return; - } - for(var i = 0; i < res.length; i++){ - var widget_id = res[i][0]; - var widget_name = res[i][1]; - let url = this.conf.api.widgetCommon + "/" + widget_id + "/framework.js"; - var header_name = widget_name; - if(res[i][7] == 1){ - header_name = (widget_name.length > 9) ?widget_name.substring(0, 8) + '...' : widget_name; - } - if(res[i][4] === "S" || res[i][4] === null ){ - $scope.widgetsList.push({ - id: widget_id, - headerName: header_name, - name: widget_name, - url: url, - attrs: [{attr: 'data-' + res[i][0], value: ''}], - x: res[i][3], - y: res[i][5], - height: res[i][6], - width: res[i][7] - }); - } - var script = document - .createElement('script'); - script.src = url; - script.async = false; - var entry = document - .getElementsByTagName('script')[0]; - entry.parentNode - .insertBefore(script, entry); - } - $scope.applyPresentationDetailsToWidgets($scope.widgetsList); - }).catch(err => { - $log.error('WidgetsHomeCtrl::getUserWidgets error: ' + err); - }).finally(()=> { - - }); - }; - - userProfileService.getUserProfile().then( - function(profile) { - $scope.orgUserId = profile.orgUserId; - getUserWidgets($scope.orgUserId); - }); - - /* Widget Gridster Section */ - $scope.newsGridsterItem = { - sizeX : 1, - sizeY : 1, - headerText : 'News', - subHeaderText : '', - imageLink : '', - order : '', - url : '' - }; - - $scope.eventsGridsterItem = { - sizeX : 1, - sizeY : 1, - headerText : 'Events', - subHeaderText : '', - imageLink : '', - order : '', - url : '' - }; - - $scope.impoResGridsterItem = { - sizeX : 1, - sizeY : 1, - headerText : 'Resources', - subHeaderText : '', - imageLink : '', - order : '', - url : '' - }; - - this.gridsterAppOpts = { - columns : 6, - colWidth : 190, - rowHeight : 190, - margins : [ 20, 20 ], - outerMargin : true, - pushing : true, - floating : true, - swapping : true, - resizable: { - enabled: false, - }, - draggable : { - handle:'.icon-content-gridguide', - stop: function stop() { - $scope.defaultSortBy = function() { - var resJson = {}; - resJson.value = 'M'; - resJson.index = 3; - resJson.title = 'Manual'; - $scope.selectedSortType = resJson; - applicationsService.saveAppsSortTypeManual($scope.appsViewData) - applicationsService.saveAppsSortTypePreference($scope.selectedSortType) - } - $scope.defaultSortBy(); - } - } - }; - - this.gridsterWidgetOpts = { - columns : 6, - colWidth : 190, - rowHeight : 190, - margins : [ 20, 20 ], - outerMargin : true, - pushing : true, - floating : true, - swapping : true, - resizable: { - enabled: true, - stop: function stop(event, uiWidget, $element){ - if($element.sizeX == 1) - $element.headerText = ($element.widgetText.length > 9) ? $element.widgetText.substring(0, 8) + '...' : $element.widgetText; - if($element.sizeX >= 2) - $element.headerText = $element.widgetText; - - applicationsService - .saveWidgetsSortManual($scope.widgetsViewData) - - } - }, - draggable : { - handle:'.icon-content-gridguide', - stop: function stop(){ - applicationsService - .saveWidgetsSortManual($scope.widgetsViewData) - - } - } - }; - - this.goToCatalog = function(item) { - $state.go('root.appCatalog'); - } - - this.goToWidgetCatLog = function(item) { - $state.go('root.widgetCatalog'); - } - - // navigate to application url in new tab - this.goToPortal = function(item) { - if (!item.url) { - $log.error('No URL found for this application, doing nothing!'); - return; - } - if (item.restrictedApp) { - // Link-based apps open in their own browser tab - $window.open(item.url, '_blank'); - } else { - // cache control so browsers load app page every time - var ccParam = 'cc=' + new Date().getTime(); - var urlParts = item.url.split('#'); - var appUrl = null; - if (urlParts.length < 2) { - // no # - let urlLastChar = item.url.charAt(item.url.length - 1); - if (item.url.includes("?")) - appUrl = (urlLastChar === '&' ? item.url + ccParam : item.url + '&' + ccParam); - else - appUrl = item.url + '?' + ccParam; - } else { - // has # - let urlLastChar = urlParts[0].charAt(urlParts[0].length - 1); - if (item.url.includes("?")) - appUrl = (urlLastChar === '&' ? urlParts[0] + ccParam + '#' + urlParts[1] : urlParts[0] + '&' + ccParam + '#' + urlParts[1]); - else - appUrl = urlParts[0] + '?' + ccParam + "#" + urlParts[1]; - } - // $log.debug('DashboardCtrlr::goToPortal: opening tab with URL - // ' + appUrl); - var tabContent = { - id: new Date(), - title: item.headerText, - url: appUrl, - appId: item.appId - }; - $cookies.putObject('addTab', tabContent); - } - - }; - - this.auditLog = function(app) { - console.log(app); - auditLogService.storeAudit(app.appid,'app',app.url); - }; - - if (getParameterByName('noUserError') != null) { - if (getParameterByName('noUserError') == "Show") { - $("#errorInfo").show(); - } - } - }; - - DashboardCtrl.$inject = [ 'conf', 'applicationsService', '$log', '$window', - 'userProfileService', '$scope', '$cookies', '$timeout', '$interval', - '$modal', '$state', 'beReaderService', 'dashboardService', 'confirmBoxService', - 'auditLogService', 'ngDialog', '$compile', 'widgetsCatalogService' ]; - angular.module('ecompApp').controller('DashboardCtrl', DashboardCtrl); -})(); - -function getParameterByName(name, url) { - if (!url) - url = window.location.href; - name = name.replace(/[\[\]]/g, "\\$&"); - var regex = new RegExp("[?&]" + name + "(=([^&#]*)|&|#|$)"), results = regex - .exec(url); - if (!results) - return ''; - if (!results[2]) - return ''; - return results[2].replace(/\+/g, " "); -} +/*- + * ================================================================================ + * 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 _classCallCheck(instance, Constructor) { + if (!(instance instanceof Constructor)) { + throw new TypeError('Cannot call a class as a function'); + } +} + +(function() { + var HTTP_PROTOCOL_RGX = /https?:\/\//; + + var DashboardCtrl = function DashboardCtrl(conf, applicationsService, $log, + $window, userProfileService, $scope, $cookies, $timeout, $interval, + $modal, $state, beReaderService, dashboardService, confirmBoxService, + auditLogService,ngDialog, $compile, widgetsCatalogService) { + + this.conf = conf; + var _this = this; + + _classCallCheck(this, DashboardCtrl); + + // activate spinner + this.isLoading = true; + this.isCommError = false; + $scope.getUserAppsIsDone = false; + this.userProfileService = userProfileService; + $scope.demoNum = 1; + $scope.event_content_show = false; + $scope.widgetData = []; + $scope.activateThis = function(ele){ + $compile(ele.contents())($scope); + $scope.$apply(); + }; + + $scope.editWidgetModalPopup = function(availableData, resourceType) { + $scope.editData = JSON.stringify(availableData); + $scope.availableDataTemp = $scope.availableData; + ngDialog.open({ + templateUrl : 'app/views/dashboard/dashboard-widget-manage.html', + controller : 'CommonWidgetController', + resolve : { + message : function message() { + var message = { + type : resourceType, + availableData : $scope.editData + }; + return message; + } + } + }).closePromise.then(needUpdate => { + if(resourceType=='NEWS'){ + $scope.updateNews(); + }else if(resourceType=='EVENTS'){ + $scope.updateEvents(); + }else if(resourceType=='IMPORTANTRESOURCES'){ + $scope.updateImportRes(); + } + }); + }; + + $scope.editWidgetParameters = function(widgetId) { + let data = { + widgetId: widgetId + } + ngDialog.open({ + templateUrl : 'app/views/dashboard/dashboard-widget-parameter-manage.html', + controller : 'WidgetParameterController', + data: data + }).closePromise.then(needUpdate => { + + }); + }; + + $scope.sort_options = [ + {index: 0, value: 'N', title: 'Name'}, + {index: 1, value: 'L', title: 'Last used'}, + {index: 2, value: 'F', title: 'Most used'}, + {index: 3, value: 'M', title: 'Manual'} + ]; + + $scope.selectedSortTypeChanged = function(userAppSortTypePref) { + $scope.appsViewData = []; + $scope.appsView = []; + + $scope.sort_type = userAppSortTypePref; + + applicationsService + .getAppsOrderBySortPref(userAppSortTypePref) + .then(function(res) { + _this.apps = res; + $scope.applyPresentationDetailsToApps(_this.apps); + }) + applicationsService + .saveAppsSortTypePreference($scope.selectedSortType) + .then(function(res) { + // Nothing to do + }) + + } + $scope.$watch('selectedSortType.value', (newVal, oldVal) => { + for(var i=0;i<$scope.sort_options.length;i++){ + if($scope.sort_options[i].value==newVal){ + $scope.selectedSortType=angular.copy($scope.sort_options[i]);; + } + } + }); + + $scope.restoreSortSelected = function(){ + confirmBoxService.confirm("Restore the default size and position of all widgets?").then( + function(confirmed){ + var checkConfirm = confirmed; + if(checkConfirm === true){ + applicationsService + .delWidgetsSortPref($scope.widgetsViewData).then(function(){ + $state.reload(); + }); + } + }); + /* if(confirm('Restore the default size and position of all widgets?') == true) + { + applicationsService + .delWidgetsSortPref($scope.widgetsViewData).then(function(){ + $state.reload(); + }) + }*/ + + } + + $scope.applyPresentationDetailsToApps = function(appsReturned) { + var rowNo = 0; + for (var i = 0; i < _this.apps.length; i++) { + $scope.appsView[i] = { + sizeX : 1, + sizeY : 1, + headerText : '', + subHeaderText : '', + imageLink : '', + order : '', + url : '', + appid: '', + }; + $scope.appsView[i].headerText = appsReturned[i].name; + $scope.appsView[i].subHeaderText = appsReturned[i].notes; + let imgLnk = ''; + if (appsReturned[i].imageUrl) + imgLnk = conf.api.appThumbnail.replace(':appId', appsReturned[i].id); + //$log.debug('DashboardCtlr::applyPresn: imgLink = ' + imgLnk); + $scope.appsView[i].imageLink = imgLnk; + $scope.appsView[i].order = appsReturned[i].order; + $scope.appsView[i].url = appsReturned[i].url; + $scope.appsView[i].restrictedApp = appsReturned[i].restrictedApp; + $scope.appsView[i].appid = appsReturned[i].id; + } + $scope.appsView[_this.apps.length] = { + addRemoveApps : true, + sizeX : 1, + sizeY : 1, + headerText : 'Add/Remove Applications', + subHeaderText : '', + imageLink : 'assets/images/cloud.png', + order : '', + restrictedApp : false, + url : '', + }; + if($scope.appsView.length>6){ + $(".dashboard-boarder").css({ + "height" : "400px" + }); + }else{ + $(".dashboard-boarder").css({ + "height" : "210px" + }); + } + + if ($scope.appsView != undefined + && $scope.appsView != null + && $scope.appsView.length > 0) { + $scope.appsViewData = $scope.appsView; + } + } + +$scope.widgetsView = []; + + $scope.applyPresentationDetailsToWidgets = function(widgetsReturned){ + var rowNo = 0; + for (var i = 0; i < widgetsReturned.length; i++) { + $scope.widgetsView[i] = { + sizeX : '', + sizeY :'', + headerText:'', + widgetText:'', + widgetIdentifier : '', + url : '', + widgetid: '', + attrb:'', + row:'', + col:'', + }; + $scope.widgetsView[i].widgetid = widgetsReturned[i].id; + $scope.widgetsView[i].headerText = widgetsReturned[i].headerName; + $scope.widgetsView[i].widgetText = widgetsReturned[i].name; + + if(widgetsReturned[i].headerName.toLowerCase() === 'news'){ + $scope.widgetsView[i].widgetIdentifier = 'NEWS'; + } + else + if(widgetsReturned[i].headerName.toLowerCase() === 'resources'){ + $scope.widgetsView[i].widgetIdentifier = 'IMPORTANTRESOURCES'; + } + else + if(widgetsReturned[i].headerName.toLowerCase() === 'events'){ + $scope.widgetsView[i].widgetIdentifier = 'EVENTS'; + } + + $scope.widgetsView[i].url = widgetsReturned[i].url; + $scope.widgetsView[i].attrb = widgetsReturned[i].attrs; + if(widgetsReturned[i].width === null){ + $scope.widgetsView[i].sizeX = 2; + }else{ + $scope.widgetsView[i].sizeX = widgetsReturned[i].width; + } + if(widgetsReturned[i].height === null){ + $scope.widgetsView[i].sizeY = 2; + }else{ + $scope.widgetsView[i].sizeY = widgetsReturned[i].height; + } + $scope.widgetsView[i].row = widgetsReturned[i].x; + $scope.widgetsView[i].col = widgetsReturned[i].y; + } + if ($scope.widgetsView != undefined + && $scope.widgetsView != null + && $scope.widgetsView.length > 0) { + $scope.widgetsViewData = $scope.widgetsView; + } + } + + applicationsService + .getUserAppsSortTypePreference().then(function(res) { + var resJson = {}; + resJson.value = res; + if (resJson.value==="N" || resJson.value==="") { + resJson.index = 0; + resJson.title = 'Name'; + }else if (resJson.value==="L") { + resJson.index = 1; + resJson.title = 'Last used'; + }else if(resJson.value==="F"){ + resJson.index = 2; + resJson.title = 'Most used'; + }else { + resJson.index = 3; + resJson.title = 'Manual'; + } + $scope.selectedSortType = resJson; + $scope.selectedSortTypeChanged(res); + + + }); + + $scope.widgetsList = []; + + let getUserWidgets = (loginName) => { + var conf = this.conf; + widgetsCatalogService.getUserWidgets(loginName).then(res => { + if(!(res instanceof Array)){ + this.isCommError = true; + return; + } + for(var i = 0; i < res.length; i++){ + var widget_id = res[i][0]; + var widget_name = res[i][1]; + let url = this.conf.api.widgetCommon + "/" + widget_id + "/framework.js"; + var header_name = widget_name; + if(res[i][7] == 1){ + header_name = (widget_name.length > 9) ?widget_name.substring(0, 8) + '...' : widget_name; + } + if(res[i][4] === "S" || res[i][4] === null ){ + $scope.widgetsList.push({ + id: widget_id, + headerName: header_name, + name: widget_name, + url: url, + attrs: [{attr: 'data-' + res[i][0], value: ''}], + x: res[i][3], + y: res[i][5], + height: res[i][6], + width: res[i][7] + }); + } + var script = document + .createElement('script'); + script.src = url; + script.async = false; + var entry = document + .getElementsByTagName('script')[0]; + entry.parentNode + .insertBefore(script, entry); + } + $scope.applyPresentationDetailsToWidgets($scope.widgetsList); + }).catch(err => { + $log.error('WidgetsHomeCtrl::getUserWidgets error: ' + err); + }).finally(()=> { + + }); + }; + + userProfileService.getUserProfile().then( + function(profile) { + $scope.orgUserId = profile.orgUserId; + getUserWidgets($scope.orgUserId); + }); + + /* Widget Gridster Section */ + $scope.newsGridsterItem = { + sizeX : 1, + sizeY : 1, + headerText : 'News', + subHeaderText : '', + imageLink : '', + order : '', + url : '' + }; + + $scope.eventsGridsterItem = { + sizeX : 1, + sizeY : 1, + headerText : 'Events', + subHeaderText : '', + imageLink : '', + order : '', + url : '' + }; + + $scope.impoResGridsterItem = { + sizeX : 1, + sizeY : 1, + headerText : 'Resources', + subHeaderText : '', + imageLink : '', + order : '', + url : '' + }; + + this.gridsterAppOpts = { + columns : 6, + colWidth : 190, + rowHeight : 190, + margins : [ 20, 20 ], + outerMargin : true, + pushing : true, + floating : true, + swapping : true, + resizable: { + enabled: false, + }, + draggable : { + handle:'.icon-content-gridguide', + stop: function stop() { + $scope.defaultSortBy = function() { + var resJson = {}; + resJson.value = 'M'; + resJson.index = 3; + resJson.title = 'Manual'; + $scope.selectedSortType = resJson; + applicationsService.saveAppsSortTypeManual($scope.appsViewData) + applicationsService.saveAppsSortTypePreference($scope.selectedSortType) + } + $scope.defaultSortBy(); + } + } + }; + + this.gridsterWidgetOpts = { + columns : 6, + colWidth : 190, + rowHeight : 190, + margins : [ 20, 20 ], + outerMargin : true, + pushing : true, + floating : true, + swapping : true, + resizable: { + enabled: true, + stop: function stop(event, uiWidget, $element){ + if($element.sizeX == 1) + $element.headerText = ($element.widgetText.length > 9) ? $element.widgetText.substring(0, 8) + '...' : $element.widgetText; + if($element.sizeX >= 2) + $element.headerText = $element.widgetText; + + applicationsService + .saveWidgetsSortManual($scope.widgetsViewData) + + } + }, + draggable : { + handle:'.icon-content-gridguide', + stop: function stop(){ + applicationsService + .saveWidgetsSortManual($scope.widgetsViewData) + + } + } + }; + + this.goToCatalog = function(item) { + $state.go('root.appCatalog'); + } + + this.goToWidgetCatLog = function(item) { + $state.go('root.widgetCatalog'); + } + + // navigate to application url in new tab + this.goToPortal = function(item) { + userProfileService.getUserRolesForApplication($scope.orgUserId,item.appid) + .then(res=>{ + var count = 0; + for(var i=0;i0 && res.length == count)||res.length==0) + { + confirmBoxService.showInformation('You have no roles assigned to this application to access.').then(isConfirmed => {}); + + } + else{ + if (!item.url) { + $log.error('No URL found for this application, doing nothing!'); + return; + } + if (item.restrictedApp) { + // Link-based apps open in their own browser tab + $window.open(item.url, '_blank'); + } else { + // cache control so browsers load app page every time + var ccParam = 'cc=' + new Date().getTime(); + var urlParts = item.url.split('#'); + var appUrl = null; + if (urlParts.length < 2) { + // no # + let urlLastChar = item.url.charAt(item.url.length - 1); + if (item.url.includes("?")) + appUrl = (urlLastChar === '&' ? item.url + ccParam : item.url + '&' + ccParam); + else + appUrl = item.url + '?' + ccParam; + } else { + // has # + let urlLastChar = urlParts[0].charAt(urlParts[0].length - 1); + if (item.url.includes("?")) + appUrl = (urlLastChar === '&' ? urlParts[0] + ccParam + '#' + urlParts[1] : urlParts[0] + '&' + ccParam + '#' + urlParts[1]); + else + appUrl = urlParts[0] + '?' + ccParam + "#" + urlParts[1]; + } + // $log.debug('DashboardCtrlr::goToPortal: opening tab with URL + // ' + appUrl); + var tabContent = { + id: new Date(), + title: item.headerText, + url: appUrl, + appId: item.appId + }; + $cookies.putObject('addTab', tabContent); + } + + } + }); + + + + + }; + + this.auditLog = function(app) { + console.log(app); + auditLogService.storeAudit(app.appid,'app',app.url); + }; + + if (getParameterByName('noUserError') != null) { + if (getParameterByName('noUserError') == "Show") { + $("#errorInfo").show(); + } + } + }; + + DashboardCtrl.$inject = [ 'conf', 'applicationsService', '$log', '$window', + 'userProfileService', '$scope', '$cookies', '$timeout', '$interval', + '$modal', '$state', 'beReaderService', 'dashboardService', 'confirmBoxService', + 'auditLogService', 'ngDialog', '$compile', 'widgetsCatalogService' ]; + angular.module('ecompApp').controller('DashboardCtrl', DashboardCtrl); +})(); + +function getParameterByName(name, url) { + if (!url) + url = window.location.href; + name = name.replace(/[\[\]]/g, "\\$&"); + var regex = new RegExp("[?&]" + name + "(=([^&#]*)|&|#|$)"), results = regex + .exec(url); + if (!results) + return ''; + if (!results[2]) + return ''; + return results[2].replace(/\+/g, " "); +} diff --git a/ecomp-portal-FE-common/client/app/views/dashboard/dashboard.less b/ecomp-portal-FE-common/client/app/views/dashboard/dashboard.less index bf6530b4..ac2a3cba 100644 --- a/ecomp-portal-FE-common/client/app/views/dashboard/dashboard.less +++ b/ecomp-portal-FE-common/client/app/views/dashboard/dashboard.less @@ -1,901 +1,910 @@ -.w-ecomp-dashboard-home { - .bg_portalWhite;//white for 1702 - position: @page-main-position; - top: @page-main-top; - left: @page-main-left; - right: @page-main-right; - bottom: @page-main-bottom; - padding-top: @padding-top; - overflow-y: @page-main-overflow-y; - padding-left: @padding-left-side; - - .gridster-item-container .gridster-item-body { - overflow-y:auto; - overflow-x:hidden; - } - - .dashboard-home-container { - position: relative; - padding-right: 0; - padding-left: 0; - padding-bottom: @container-bottom; - - .dashboard-home-title { - .blackText24m; - margin: auto; - .content_justify; - } - - .portals-list { - min-height: 70vh; - //display: flex; - justify-content: center; - flex-flow: row wrap; - width: @table-width; - //margin-left: 230px; - margin-bottom: 63px; - margin:auto; - .app-gridster-header { - background-color: @u; - font-size:12px; - overflow:hidden - } - - .app-gridster-footer { - background-color: @u; - } - - .portals-list-item { - background-color: @u; - border-radius: 2px; - box-shadow: 0px -1px 2px 0px rgba(0, 0, 0, 0.1); - display: inline-block; - width: 360px; - height: 300px; - background-size: cover; - cursor: pointer; - margin: 15px; - overflow: hidden; - - .portals-item-info { - background-color: @u; - height: 120px; - top: 180px; - position: relative; - box-shadow: 0px -1px 2px 0px rgba(0, 0, 0, 0.1); - padding: 16px; - - .info-title { - .blackText24m; - margin-bottom: 4px; - - text-overflow: ellipsis; - overflow: hidden; - } - .info-description { - .portalDBlue16r; - text-overflow: ellipsis; - white-space: nowrap; - overflow: hidden; - } - .info-button { - .btn-green; - width: 96px; - position: absolute; - bottom: 16px; - left: 16px; - } - - &:hover { - opacity: .93; - z-index: 3; - } - } - } - } - } -} -.w-ecomp-main-error{ - .portalRed; - position: absolute; - width: 100%; - line-height: 1.5em; -} -.w-ecomp-main-disclaimer { - text-align: center; - .dGray14r; - //position: absolute; - bottom: -75px; - line-height: 1.5em; - margin: 0 auto; - width:1170px; - position: relative; - -} - -@keyframes fadein { - from { - opacity: 0; - } - to { - opacity: 1; - } -} - -.slide.ng-hide-add, -.slide.ng-hide-remove, -.slide.ng-enter, -.slide.ng-leave { - transition: all 0.5s ease; -} -.slide.ng-hide, -.slide.ng-enter { - transform: translate(-100%, 0); -} -.slide.ng-enter-active { - transform: translate(0, 0); -} -.slide.ng-leave { - transform: translate(0, 0); -} -.slide.ng-leave-active { - transform: translate(+100%, 0); -} -.dashboard-boarder{ - // border: 2px solid #ccc!important; - // border-radius: 16px!important; - height: 210px; - overflow: auto; -} -.dashboard-information-boarder{ - border: 2px solid #ccc!important; - border-radius: 16px!important; -} - -#information-section { - margin-top:50px; -} - -.information-section-title{ - color: #0574ac; - font-family: Omnes-ECOMP-W02-Bold,Arial; - font-size: 25px; - margin: 20px; - width: 1170px; -} -#left { - float: left; - width: 33%; - height:300px; - background-color: white; -} - -#center { - float: right; - width: 33%; - height:300px; - background: white; -} -#right { - margin-left:34%; - margin-right:34%; - height:300px; - background:white; -} - - -/*hover*/ - - -.dock ul{ -display: inline-block; - -width: auto; -margin: 0px; -padding: 0px; -list-style: none; - -} -.dock ul li { -width: auto; -height: auto; -display: inline-block; -bottom: 0; -vertical-align: bottom; -margin-top: -43px; -} -.dock ul li a { -display: block; -height: 150px; -width: 150px; -position: relative; --webkit-transition-property: width, height,margin-top; --webkit-transition-duration: 0.5s; --o-transition-property: width, height,margin-top; --o-transition-duration: 0.5s; --moz-transition-property: width, height,margin-top; --moz-transition-duration: 0.5s; -} -.dock ul li a:hover { -width: 200px; -height: 200px; -margin-top: -50px; -} -.dock ul li a img { -width: 100%; -position: absolute; -bottom: 0; -left: 0; -border: none; -padding: 0px 0px 0px 30px; -} -.dock_left{ -width: 31px; --webkit-transform: rotate(33deg); --moz-transform: rotate(33deg); --o-transform: rotate(33deg); -position: relative; -background: #EEE; -overflow: hidden; -float: left; -height: 100px; -z-index: 2; -margin: -18px; -} -.dock_right{ -width: 36px; --webkit-transform: rotate(-33deg); --moz-transform: rotate(-33deg); --o-transform: rotate(-33deg); -position: relative; -background: #EEE; -overflow: hidden; -float: left; -height: 100px; -z-index: 2; -margin: -18px; -} - - - - -/*Time for the CSS*/ -* {margin: 0; padding: 0;} -body {background: #ccc;} - -.slider{ - width: 640px; /*Same as width of the large image*/ - position: relative; - /*Instead of height we will use padding*/ - padding-top: 320px; /*That helps bring the labels down*/ - - margin: 50px auto; - - /*Lets add a shadow*/ - box-shadow: 0 10px 20px -5px rgba(0, 0, 0, 0.75); -} - - -/*Last thing remaining is to add transitions*/ -.slider>img{ - position: absolute; - left: 0; top: 0; - transition: all 0.5s; -} - -.slider input[name='slide_switch'] { - display: none; -} - -.slider label { - /*Lets add some spacing for the thumbnails*/ - margin: 18px 0 0 18px; - border: 3px solid #999; - - float: left; - cursor: pointer; - transition: all 0.5s; - - /*Default style = low opacity*/ - opacity: 0.6; -} - -.slider label img{ - display: block; -} - -/*Time to add the click effects*/ -.slider input[name='slide_switch']:checked+label { - border-color: #666; - opacity: 1; -} -/*Clicking any thumbnail now should change its opacity(style)*/ -/*Time to work on the main images*/ -.slider input[name='slide_switch'] ~ img { - opacity: 0; - transform: scale(1.1); -} -/*That hides all main images at a 110% size -On click the images will be displayed at normal size to complete the effect -*/ -.slider input[name='slide_switch']:checked+label+img { - opacity: 1; - transform: scale(1); -} -/*Clicking on any thumbnail now should activate the image related to it*/ - -/*We are done :)*/ - - - -.accordion { - width: 895px; height: 320px; - overflow: hidden; - box-shadow: 0 10px 6px -6px #111; - margin: 20px auto -} -.accordion ul { width: 200% } - -.accordion li { - position: relative; - display: block; - width: 160px; - float: left; - box-shadow: 0 0 30px 8px #222; - transition: all 0.4s ease .300ms; -} - -.accordion ul:hover li {width: 40px } -.accordion ul li:hover {width: 640px } - -.caption { - background: rgba(0, 0, 0, 0.5); - position: absolute; - bottom: 0; - width: 640px -} - -.caption a { - display: block; - color: #fff; - text-decoration: none; - font: normal 16px 'Lato', Helvetica, Arial, sans-serif; - -webkit-font-smoothing: antialiased; - padding: 15px; -} - - -/*events*/ -.events-date{ - margin-left: 10px; - float:left; - white-space: normal; - display: inline-block; - vertical-align: middle; - width: 55px; -} -.event-title-div{ - float: left; - width: 235px; - line-height: 20px; - padding: 5px; - font-size: 14px; - margin-left: 4px; -} -.events-date{ - height: 20px; - margin-left: 4px; - font-size: 14px; -} -.events-content{ - font-size: 14px; - color: #444; - margin-right: 10px; -} -.events-content-body{ - margin-top:5px; - color:#444; - margin-left:12px; - line-height:1.5; -} -.events { - border-radius: 4px; - padding: 3px; - -webkit-user-select: none; -} -.events ul { - float: left; - width:100%; - -webkit-user-select: none -} -.events ul li { - line-height: 30px; - list-style: none; - border-bottom: 2px solid grey; - height: 100%; - min-height: 42px; -} -.events ul li:hover { - background: #ddd; - cursor: pointer; -} -.events ul li a { - color: black; - text-decoration: none; - font: 14px Helvetica, Arial, sans-serif; - -webkit-font-smoothing: antialiased; - -webkit-user-select: none; - font-family: "Omnes-ECOMP-W02", Arial; -} -.events-link{ - color: #067ab4 !important; -} - - -/*widgets*/ - -.handle-e{ - width: 5px; -} - -.singleBtnBorder { - border-radius: 6px 6px 6px 6px; -} - -.widgetHeaderBtn{ - - height: 30px; - background-color: #FFFFFF; - position: relative; - display: inline-block; - -moz-background-clip: padding-box; - -webkit-background-clip: padding-box; - background-clip: padding-box; - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; - padding: 8px 20px; - font-size: 14px; - line-height: 14px; - min-width: 60px; - border: none; - border-radius: 6px; - background-color: #ffffff; - background-image: none; - color: #ffffff; - vertical-align: middle; - text-align: center; - text-decoration: none; - text-transform: capitalize; - text-shadow: none !important; - white-space: nowrap; - cursor: pointer; - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - -o-user-select: none; - user-select: none; - -webkit-transition: background-color 0.3s ease-out; - -moz-transition: background-color 0.3s ease-out; - transition: background-color 0.3s ease-out; - } - -.widgetHeaderBtnPosition { - width: 30px; - min-width: 0px; - border: 1px solid #AAAAAA; - padding-left: 3px; - padding-right: 5px; - } - -.icon-anchor { - color: #888; -} - -.widgetHeaderBtn:hover, .widgetHeaderBtn:focus { - background: rgba(0, 0, 0, 0); - color: #3a7999; - box-shadow: inset 0 0 0 2px #3a7999; -} -/*news*/ - -@keyframes ticker { - 0% {margin-top: 0} - 25% {margin-top: -55px} - 50% {margin-top: -110px} - 75% {margin-top: -165px} - 100% {margin-top: 0} -} - -body { background: #333; width: 100%; height: 100% } - -.news { - - width: 350px; - height: 250px; - margin: 0px auto; - // overflow: auto; - border-radius: 4px; - padding: 3px; - -webkit-user-select: none; - -} - - - -.news ul { - float: left; - width:100%; - // animation: ticker 25s cubic-bezier(1, 0, .5, 0) infinite; - -webkit-user-select: none -} - -.news ul li {line-height: 30px; list-style: none; - border-bottom: 2px solid grey; - min-height: 42px; - } - -.news ul li:hover { - background: #ddd; - cursor: pointer; -} - -.news ul li a { - color: black; - text-decoration: none; - font-size: 14px; - line-height: 1.5; - display: inline-block; - width:100%; - min-height:40px; - padding-top: 5px; - padding-bottom: 5px; - -webkit-font-smoothing: antialiased; - -webkit-user-select: none; -} - -.news ul:hover { animation-play-state: paused } -.news span:hover+ul { animation-play-state: paused } -/*resources*/ -.resources { - - width: 100%; - height: 200px; - margin-left: 5px; - border-radius: 4px; - padding: 3px; - -webkit-user-select: none; - -} - - - -.resources ul { - float: left; - width:100%; - - -webkit-user-select: none -} - -.resources ul li {line-height: 30px; list-style: none; - border-bottom: 2px solid grey; - min-height: 42px; - } - -.resources ul li:hover { - background: #ddd; - cursor: pointer; -} - -.resources ul li a { - color: black; - text-decoration: none; - font-size: 14px; - line-height: 1.5; - width:100%; - min-height:40px; - display: inline-block; - padding-top: 5px; - padding-bottom: 5px; - -webkit-font-smoothing: antialiased; - -webkit-user-select: none; -} - - -/* OTHER COLORS */ -.blue { background: #347fd0 } -.blue span { background: #2c66be } -.red { background: #d23435 } -.red span { background: #c22b2c } -.green { background: #699B67 } -.green span { background: #547d52 } -.magenta { background: #b63ace } -.magenta span { background: #842696 } - - -/*broadcast*/ - -.box-one { - -webkit-transition:all linear 0.4s; - transition:all linear 0.4s; - height:100px; width:200px; background:white; border: 2px solid #ccc!important; - border-radius: 16px!important; -} -.box-one.ng-hide { -display: block!important; - opacity:0; -} - -.gridsterContent{ - height:120px; -} - -.gridster-item{ - z-index:0 !important; -} -.gridsterAppContent{ - height:120px; - -} - - .gridsterImage{ - height:84px; - width:168px; - } - .grider-content-ecomp{ - transition: transform 0.5s ease-out; - } - .grider-content-ecomp:hover{ - transform: scale(1.1); -} - - -/*information section*/ - -.information-section{ - /*margin-top:25px;*/ -} -.information-section-gridsterContent{ - /*height:300px;*/ -} -.information-sections-gridster-header{ - color: #0574ac; - font-family: Omnes-ECOMP-W02-Bold,Arial; - font-size: 25px; - -} -/*application empty div*/ -.app-error-block { - padding-top: 10px; - -} -/*news empty div*/ -.activity-error-block { - padding-top: 60px; - -} - -.activity-error-msg1{ - text-align: center; - margin-top: 20px; - font-family: "Omnes-ECOMP-W02", Arial; - color: #444; - font-size: 20px; - -} - -.newstape { - background: white; - color: black; - height: 400px; - overflow: hidden; -} - -.newstape-content { - position: relative; - padding: 15px; -} - -.newstape-drag { cursor: ns-resize; } - -.text-center { text-align: center; } - -.text-right { text-align: right; } - -.text-justify { text-align: justify; } - -// #newsContainer{ -// overflow:auto; -// height: 100%; -// } - -/*widget header*/ -.optionsMenu{ - position: absolute; - list-style: none; - top: 25px; - right: 10px; - border: 1px solid #067ab4; - display: none; - z-index: 2; - border-radius: 6px 0px 6px 6px; - background: #fff; - width: 130px; -} - -.optionsMenuLink { - position: relative; - padding-left: 8px; - padding-right: 2px; - font-size: 12px; - line-height: 30px; - color: #444444; -} -.optionsMenu > li:hover a { - color: #ffffff !important; -} -.optionsMenu > li { - width: 100%; - text-align: left; -} -.optionsMenu > li:hover { - background-color: #0faaf7; - border-color: none !important; - cursor: pointer; -} - -.dashboardSortHeader{ - margin-left: 756px; -} - -#dashboardAddWidgetPreference{ - display: inline-block; - font-size: 14px; - color: #3e3e3e; - width: 69%; - text-align: center; - padding: 15px 0px 15px 0px; - font-family: "Omnes-ECOMP-W02", Arial; -} - -#dashboardAddWidgetPreference:hover{ - background-color: #0568ae; - color:white !important; -} - -#dashboardDefaultPreference{ - display: inline-block; - font-size: 14px; - color: #3e3e3e; - width: 30%; - text-align: center; - padding: 15px 0px 15px 0px; - font-family: "Omnes-ECOMP-W02", Arial; -} - -#dashboardDefaultPreference:hover{ - background-color: #0568ae; - color:white !important; -} - -.simulateGridHeader{ - position: relative; - height: 50px !important; - border: 1px solid #d3d3d3; - border-bottom: 0; - background-color: #E5E5E5; - white-space: nowrap; - text-overflow: ellipsis; - z-index: 1; -} - -.simulateGridHeaderTitle{ - line-height: 44px; - margin-left: 26px; - font-family: "Omnes-ECOMP-W02", Arial; - font-size: 18px; - color: #444444; - float: left; -} - -.simulateGridHeaderHandle{ - cursor: move; - margin: 12px; - position: absolute; - top: 0; - left: 0; - border: 0; - vertical-align: middle; - -ms-interpolation-mode: bicubic; - display: block; -} - -/* apps gridsters */ -ul { - list-style: none; -} -.gridster-box { - height: 100%; - border: 1px solid #ccc; - background-color: #fff; - transition: transform 0.5s ease-out; -} -.gridster-box-header { - background-color: #fff; - padding: 0 0px 0 10px; - border-bottom: 1px solid #ccc; - position: relative; - height: 50px !important; -} -.gridster-box-header h3 { - margin-top: 15px; - display: inline-block; - font-family: "Omnes-ECOMP-W02", Arial; -} - -.gridster-box-header i { -font-size: 22px; -} - -.gridster-box-content { - padding: 59px; -} -.gridster-box:hover{ - transform: scale(1.1); -} -.gridster-box-header-btns { - top: 15px; - right: 10px; - position: absolute; -} - -/*** widgets ***/ -ul { - list-style: none; -} -.box { - height: 100%; - border: 1px solid #ccc; - background-color: #fff; - font-family: "Omnes-ECOMP-W02", Arial; -} -.box-header { - height : 50px; - background-color: #fff; - padding: 0 30px 0 10px; - border-bottom: 1px solid #ccc; - position: relative; -} -.box-header h3 { - margin-top: 15px; - display: inline-block; - font-size: 16px; -} -.box-content { - position: absolute; - width: 100%; - top: 50px; - left: 0; - right: 0; - bottom: 29px; - border: 1px solid #d3d3d3; - box-sizing: border-box; - overflow-y: auto; - overflow-x: hidden; - color: #444444; - bottom: 0px; -} -.box-header-btns { - top: 10px; - right: 10px; - cursor: pointer; - position: absolute; -} - -#widget-boarder{ - background-color: #eee; - border: 1px dashed white; -} -.icon-content-gridguide{ -cursor:move; +.w-ecomp-dashboard-home { + .bg_portalWhite;//white for 1702 + position: @page-main-position; + top: @page-main-top; + left: @page-main-left; + right: @page-main-right; + bottom: @page-main-bottom; + padding-top: @padding-top; + overflow-y: @page-main-overflow-y; + padding-left: @padding-left-side; + + .gridster-item-container .gridster-item-body { + overflow-y:auto; + overflow-x:hidden; + } + + .dashboard-home-container { + position: relative; + padding-right: 0; + padding-left: 0; + padding-bottom: @container-bottom; + + .dashboard-home-title { + .blackText24m; + margin: auto; + .content_justify; + } + + .portals-list { + min-height: 70vh; + //display: flex; + justify-content: center; + flex-flow: row wrap; + width: @table-width; + //margin-left: 230px; + margin-bottom: 63px; + margin:auto; + .app-gridster-header { + background-color: @u; + font-size:12px; + overflow:hidden + } + + .app-gridster-footer { + background-color: @u; + } + + .portals-list-item { + background-color: @u; + border-radius: 2px; + box-shadow: 0px -1px 2px 0px rgba(0, 0, 0, 0.1); + display: inline-block; + width: 360px; + height: 300px; + background-size: cover; + cursor: pointer; + margin: 15px; + overflow: hidden; + + .portals-item-info { + background-color: @u; + height: 120px; + top: 180px; + position: relative; + box-shadow: 0px -1px 2px 0px rgba(0, 0, 0, 0.1); + padding: 16px; + + .info-title { + .blackText24m; + margin-bottom: 4px; + + text-overflow: ellipsis; + overflow: hidden; + } + .info-description { + .portalDBlue16r; + text-overflow: ellipsis; + white-space: nowrap; + overflow: hidden; + } + .info-button { + .btn-green; + width: 96px; + position: absolute; + bottom: 16px; + left: 16px; + } + + &:hover { + opacity: .93; + z-index: 3; + } + } + } + } + } +} +.w-ecomp-main-error{ + .portalRed; + position: absolute; + width: 100%; + line-height: 1.5em; +} +.w-ecomp-main-disclaimer { + text-align: center; + .dGray14r; + //position: absolute; + bottom: -75px; + line-height: 1.5em; + margin: 0 auto; + width:1170px; + position: relative; + +} + +@keyframes fadein { + from { + opacity: 0; + } + to { + opacity: 1; + } +} + +.slide.ng-hide-add, +.slide.ng-hide-remove, +.slide.ng-enter, +.slide.ng-leave { + transition: all 0.5s ease; +} +.slide.ng-hide, +.slide.ng-enter { + transform: translate(-100%, 0); +} +.slide.ng-enter-active { + transform: translate(0, 0); +} +.slide.ng-leave { + transform: translate(0, 0); +} +.slide.ng-leave-active { + transform: translate(+100%, 0); +} +.dashboard-boarder{ + // border: 2px solid #ccc!important; + // border-radius: 16px!important; + height: 210px; + overflow: auto; +} +.dashboard-information-boarder{ + border: 2px solid #ccc!important; + border-radius: 16px!important; +} + +#information-section { + margin-top:50px; +} + +.information-section-title{ + color: #0574ac; + font-family: Omnes-ECOMP-W02-Bold,Arial; + font-size: 25px; + margin: 20px; + width: 1170px; +} +#left { + float: left; + width: 33%; + height:300px; + background-color: white; +} + +#center { + float: right; + width: 33%; + height:300px; + background: white; +} +#right { + margin-left:34%; + margin-right:34%; + height:300px; + background:white; +} + + +/*hover*/ + + +.dock ul{ +display: inline-block; + +width: auto; +margin: 0px; +padding: 0px; +list-style: none; + +} +.dock ul li { +width: auto; +height: auto; +display: inline-block; +bottom: 0; +vertical-align: bottom; +margin-top: -43px; +} +.dock ul li a { +display: block; +height: 150px; +width: 150px; +position: relative; +-webkit-transition-property: width, height,margin-top; +-webkit-transition-duration: 0.5s; +-o-transition-property: width, height,margin-top; +-o-transition-duration: 0.5s; +-moz-transition-property: width, height,margin-top; +-moz-transition-duration: 0.5s; +} +.dock ul li a:hover { +width: 200px; +height: 200px; +margin-top: -50px; +} +.dock ul li a img { +width: 100%; +position: absolute; +bottom: 0; +left: 0; +border: none; +padding: 0px 0px 0px 30px; +} +.dock_left{ +width: 31px; +-webkit-transform: rotate(33deg); +-moz-transform: rotate(33deg); +-o-transform: rotate(33deg); +position: relative; +background: #EEE; +overflow: hidden; +float: left; +height: 100px; +z-index: 2; +margin: -18px; +} +.dock_right{ +width: 36px; +-webkit-transform: rotate(-33deg); +-moz-transform: rotate(-33deg); +-o-transform: rotate(-33deg); +position: relative; +background: #EEE; +overflow: hidden; +float: left; +height: 100px; +z-index: 2; +margin: -18px; +} + + + + +/*Time for the CSS*/ +* {margin: 0; padding: 0;} +body {background: #ccc;} + +.slider{ + width: 640px; /*Same as width of the large image*/ + position: relative; + /*Instead of height we will use padding*/ + padding-top: 320px; /*That helps bring the labels down*/ + + margin: 50px auto; + + /*Lets add a shadow*/ + box-shadow: 0 10px 20px -5px rgba(0, 0, 0, 0.75); +} + + +/*Last thing remaining is to add transitions*/ +.slider>img{ + position: absolute; + left: 0; top: 0; + transition: all 0.5s; +} + +.slider input[name='slide_switch'] { + display: none; +} + +.slider label { + /*Lets add some spacing for the thumbnails*/ + margin: 18px 0 0 18px; + border: 3px solid #999; + + float: left; + cursor: pointer; + transition: all 0.5s; + + /*Default style = low opacity*/ + opacity: 0.6; +} + +.slider label img{ + display: block; +} + +/*Time to add the click effects*/ +.slider input[name='slide_switch']:checked+label { + border-color: #666; + opacity: 1; +} +/*Clicking any thumbnail now should change its opacity(style)*/ +/*Time to work on the main images*/ +.slider input[name='slide_switch'] ~ img { + opacity: 0; + transform: scale(1.1); +} +/*That hides all main images at a 110% size +On click the images will be displayed at normal size to complete the effect +*/ +.slider input[name='slide_switch']:checked+label+img { + opacity: 1; + transform: scale(1); +} +/*Clicking on any thumbnail now should activate the image related to it*/ + +/*We are done :)*/ + + + +.accordion { + width: 895px; height: 320px; + overflow: hidden; + box-shadow: 0 10px 6px -6px #111; + margin: 20px auto +} +.accordion ul { width: 200% } + +.accordion li { + position: relative; + display: block; + width: 160px; + float: left; + box-shadow: 0 0 30px 8px #222; + transition: all 0.4s ease .300ms; +} + +.accordion ul:hover li {width: 40px } +.accordion ul li:hover {width: 640px } + +.caption { + background: rgba(0, 0, 0, 0.5); + position: absolute; + bottom: 0; + width: 640px +} + +.caption a { + display: block; + color: #fff; + text-decoration: none; + font: normal 16px 'Lato', Helvetica, Arial, sans-serif; + -webkit-font-smoothing: antialiased; + padding: 15px; +} + + +/*events*/ +.events-date{ + margin-left: 10px; + float:left; + white-space: normal; + display: inline-block; + vertical-align: middle; + width: 55px; +} +.event-title-div{ + float: left; + width: 235px; + line-height: 20px; + padding: 5px; + font-size: 14px; + margin-left: 4px; +} +.events-date{ + height: 20px; + margin-left: 4px; + font-size: 14px; +} +.events-content{ + font-size: 14px; + color: #444; + margin-right: 10px; +} +.events-content-body{ + margin-top:5px; + color:#444; + margin-left:12px; + line-height:1.5; +} +.events { + border-radius: 4px; + padding: 3px; + -webkit-user-select: none; +} +.events ul { + float: left; + width:100%; + -webkit-user-select: none +} +.events ul li { + line-height: 30px; + list-style: none; + border-bottom: 2px solid grey; + height: 100%; + min-height: 42px; +} +.events ul li:hover { + background: #ddd; + cursor: pointer; +} +.events ul li a { + color: black; + text-decoration: none; + font: 14px Helvetica, Arial, sans-serif; + -webkit-font-smoothing: antialiased; + -webkit-user-select: none; + font-family: "Omnes-ECOMP-W02", Arial; +} +.events-link{ + color: #067ab4 !important; +} + + +/*widgets*/ + +.handle-e{ + width: 5px; +} + +.singleBtnBorder { + border-radius: 6px 6px 6px 6px; +} + +.widgetHeaderBtn{ + + height: 30px; + background-color: #FFFFFF; + position: relative; + display: inline-block; + -moz-background-clip: padding-box; + -webkit-background-clip: padding-box; + background-clip: padding-box; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; + padding: 8px 20px; + font-size: 14px; + line-height: 14px; + min-width: 60px; + border: none; + border-radius: 6px; + background-color: #ffffff; + background-image: none; + color: #ffffff; + vertical-align: middle; + text-align: center; + text-decoration: none; + text-transform: capitalize; + text-shadow: none !important; + white-space: nowrap; + cursor: pointer; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + -o-user-select: none; + user-select: none; + -webkit-transition: background-color 0.3s ease-out; + -moz-transition: background-color 0.3s ease-out; + transition: background-color 0.3s ease-out; + } + +.widgetHeaderBtnPosition { + width: 30px; + min-width: 0px; + border: 1px solid #AAAAAA; + padding-left: 3px; + padding-right: 5px; + } + +.icon-anchor { + color: #888; +} + +.widgetHeaderBtn:hover, .widgetHeaderBtn:focus { + background: rgba(0, 0, 0, 0); + color: #3a7999; + box-shadow: inset 0 0 0 2px #3a7999; +} +/*news*/ + +@keyframes ticker { + 0% {margin-top: 0} + 25% {margin-top: -55px} + 50% {margin-top: -110px} + 75% {margin-top: -165px} + 100% {margin-top: 0} +} + +body { background: #333; width: 100%; height: 100% } + +.news { + + width: 350px; + height: 250px; + margin: 0px auto; + // overflow: auto; + border-radius: 4px; + padding: 3px; + -webkit-user-select: none; + +} + + + +.news ul { + float: left; + width:100%; + // animation: ticker 25s cubic-bezier(1, 0, .5, 0) infinite; + -webkit-user-select: none +} + +.news ul li {line-height: 30px; list-style: none; + border-bottom: 2px solid grey; + min-height: 42px; + } + +.news ul li:hover { + background: #ddd; + cursor: pointer; +} + +.news ul li a { + color: black; + text-decoration: none; + font-size: 14px; + line-height: 1.5; + display: inline-block; + width:100%; + min-height:40px; + padding-top: 5px; + padding-bottom: 5px; + -webkit-font-smoothing: antialiased; + -webkit-user-select: none; +} + +.news ul:hover { animation-play-state: paused } +.news span:hover+ul { animation-play-state: paused } +/*resources*/ +.resources { + + width: 100%; + height: 200px; + margin-left: 5px; + border-radius: 4px; + padding: 3px; + -webkit-user-select: none; + +} + + + +.resources ul { + float: left; + width:100%; + + -webkit-user-select: none +} + +.resources ul li {line-height: 30px; list-style: none; + border-bottom: 2px solid grey; + min-height: 42px; + } + +.resources ul li:hover { + background: #ddd; + cursor: pointer; +} + +.resources ul li a { + color: black; + text-decoration: none; + font-size: 14px; + line-height: 1.5; + width:100%; + min-height:40px; + display: inline-block; + padding-top: 5px; + padding-bottom: 5px; + -webkit-font-smoothing: antialiased; + -webkit-user-select: none; +} + + +/* OTHER COLORS */ +.blue { background: #347fd0 } +.blue span { background: #2c66be } +.red { background: #d23435 } +.red span { background: #c22b2c } +.green { background: #699B67 } +.green span { background: #547d52 } +.magenta { background: #b63ace } +.magenta span { background: #842696 } + + +/*broadcast*/ + +.box-one { + -webkit-transition:all linear 0.4s; + transition:all linear 0.4s; + height:100px; width:200px; background:white; border: 2px solid #ccc!important; + border-radius: 16px!important; +} +.box-one.ng-hide { +display: block!important; + opacity:0; +} + +.gridsterContent{ + height:120px; +} + +.gridster-item{ + z-index:0 !important; +} +.gridsterAppContent{ + height:120px; + +} + + .gridsterImage{ + height:84px; + width:168px; + } + .grider-content-ecomp{ + transition: transform 0.5s ease-out; + } + .grider-content-ecomp:hover{ + transform: scale(1.1); +} + + +/*information section*/ + +.information-section{ + /*margin-top:25px;*/ +} +.information-section-gridsterContent{ + /*height:300px;*/ +} +.information-sections-gridster-header{ + color: #0574ac; + font-family: Omnes-ECOMP-W02-Bold,Arial; + font-size: 25px; + +} +/*application empty div*/ +.app-error-block { + padding-top: 10px; + +} +/*news empty div*/ +.activity-error-block { + padding-top: 60px; + +} + +.activity-error-msg1{ + text-align: center; + margin-top: 20px; + font-family: "Omnes-ECOMP-W02", Arial; + color: #444; + font-size: 20px; + +} + +.newstape { + background: white; + color: black; + height: 400px; + overflow: hidden; +} + +.newstape-content { + position: relative; + padding: 15px; +} + +.newstape-drag { cursor: ns-resize; } + +.text-center { text-align: center; } + +.text-right { text-align: right; } + +.text-justify { text-align: justify; } + +// #newsContainer{ +// overflow:auto; +// height: 100%; +// } + +/*widget header*/ +.optionsMenu{ + position: absolute; + list-style: none; + top: 25px; + right: 10px; + border: 1px solid #067ab4; + display: none; + z-index: 2; + border-radius: 6px 0px 6px 6px; + background: #fff; + width: 130px; +} + +.optionsMenuLink { + position: relative; + padding-left: 8px; + padding-right: 2px; + font-size: 12px; + line-height: 30px; + color: #444444; +} +.optionsMenu > li:hover a { + color: #ffffff !important; +} +.optionsMenu > li { + width: 100%; + text-align: left; +} +.optionsMenu > li:hover { + background-color: #0faaf7; + border-color: none !important; + cursor: pointer; +} + +.dashboardSortHeader{ + margin-top: -44px; +margin-left: 735px; +} + +#dashboard-dropdown +{ +position: absolute; +margin-top: -37px; +left: 80%; +top: 42px; +} + +#dashboardAddWidgetPreference{ + display: inline-block; + font-size: 14px; + color: #3e3e3e; + width: 69%; + text-align: center; + padding: 15px 0px 15px 0px; + font-family: "Omnes-ECOMP-W02", Arial; +} + +#dashboardAddWidgetPreference:hover{ + background-color: #0568ae; + color:white !important; +} + +#dashboardDefaultPreference{ + display: inline-block; + font-size: 14px; + color: #3e3e3e; + width: 30%; + text-align: center; + padding: 15px 0px 15px 0px; + font-family: "Omnes-ECOMP-W02", Arial; +} + +#dashboardDefaultPreference:hover{ + background-color: #0568ae; + color:white !important; +} + +.simulateGridHeader{ + position: relative; + height: 50px !important; + border: 1px solid #d3d3d3; + border-bottom: 0; + background-color: #E5E5E5; + white-space: nowrap; + text-overflow: ellipsis; + z-index: 1; +} + +.simulateGridHeaderTitle{ + line-height: 44px; + margin-left: 26px; + font-family: "Omnes-ECOMP-W02", Arial; + font-size: 18px; + color: #444444; + float: left; +} + +.simulateGridHeaderHandle{ + cursor: move; + margin: 12px; + position: absolute; + top: 0; + left: 0; + border: 0; + vertical-align: middle; + -ms-interpolation-mode: bicubic; + display: block; +} + +/* apps gridsters */ +ul { + list-style: none; +} +.gridster-box { + height: 100%; + border: 1px solid #ccc; + background-color: #fff; + transition: transform 0.5s ease-out; +} +.gridster-box-header { + background-color: #fff; + padding: 0 0px 0 10px; + border-bottom: 1px solid #ccc; + position: relative; + height: 50px !important; +} +.gridster-box-header h3 { + margin-top: 15px; + display: inline-block; + font-family: "Omnes-ECOMP-W02", Arial; +} + +.gridster-box-header i { +font-size: 22px; +} + +.gridster-box-content { + padding: 59px; +} +.gridster-box:hover{ + transform: scale(1.1); +} +.gridster-box-header-btns { + top: 15px; + right: 10px; + position: absolute; +} + +/*** widgets ***/ +ul { + list-style: none; +} +.box { + height: 100%; + border: 1px solid #ccc; + background-color: #fff; + font-family: "Omnes-ECOMP-W02", Arial; +} +.box-header { + height : 50px; + background-color: #fff; + padding: 0 30px 0 10px; + border-bottom: 1px solid #ccc; + position: relative; +} +.box-header h3 { + margin-top: 15px; + display: inline-block; + font-size: 16px; +} +.box-content { + position: absolute; + width: 100%; + top: 50px; + left: 0; + right: 0; + bottom: 29px; + border: 1px solid #d3d3d3; + box-sizing: border-box; + overflow-y: auto; + overflow-x: hidden; + color: #444444; + bottom: 0px; +} +.box-header-btns { + top: 10px; + right: 10px; + cursor: pointer; + position: absolute; +} + +#widget-boarder{ + background-color: #eee; + border: 1px dashed white; +} +.icon-content-gridguide{ +cursor:move; } \ No newline at end of file diff --git a/ecomp-portal-FE-common/client/app/views/dashboard/dashboard.tpl.html b/ecomp-portal-FE-common/client/app/views/dashboard/dashboard.tpl.html index 5e67526e..9a87c0ba 100644 --- a/ecomp-portal-FE-common/client/app/views/dashboard/dashboard.tpl.html +++ b/ecomp-portal-FE-common/client/app/views/dashboard/dashboard.tpl.html @@ -1,179 +1,183 @@ - -
-
- -
-
-
- Applications Sort by: -
-
-
-
-
-
-
-
- You do not have access to any application or function in ECOMP - Portal.
Please request access via MyLogins. -
-
-
- -
-
    -
  • -
    -
    - -

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

    -
    -
    -
    -
    -
    -
    - -

    Select applications...

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

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

    {{ widget.headerText}}

    -
    - ... - - - -
    -
    -
    -
    -
    -
    -
  • -
-
-
-
-
- Add Widget -
-   -
- Reset Widget Layout -
-
-
- -
-
+ +
+
+ +
+
+
+ Applications Sort by: + +
+ +
+
+ +
+
+
+
+
+
+
+ You do not have access to any application or function in ECOMP + Portal. +
+
+
+
+ +
+
    +
  • +
    +
    + +

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

    +
    + +
    +
    +
    + +

    Select applications...

    + +
    +
    + +
    +
    +
  • +
+
+ +
+ +
+
+ +

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

    {{ widget.headerText}}

    +
    + ... + + + +
    +
    +
    +
    +
    +
    +
  • +
+
+
+
+
+ Add Widget +
+   +
+ Reset Widget Layout +
+
+
+ +
+
-- cgit 1.2.3-korg