summaryrefslogtreecommitdiffstats
path: root/ecomp-portal-FE/client/app/views/dashboard
diff options
context:
space:
mode:
authortalasila <talasila@research.att.com>2017-02-07 15:03:57 -0500
committertalasila <talasila@research.att.com>2017-02-07 15:05:15 -0500
commit4ad39a5c96dd99acf819ce189b13fec946d7506b (patch)
treea1449286441947cc3d07a45227fa0d6f978e1a7d /ecomp-portal-FE/client/app/views/dashboard
parent5500448cbd1f374d0ac743ee2fd636fe2d3c0027 (diff)
Initial OpenECOMP Portal commit
Change-Id: I804b80e0830c092e307da1599bd9fbb5c3e2da77 Signed-off-by: talasila <talasila@research.att.com>
Diffstat (limited to 'ecomp-portal-FE/client/app/views/dashboard')
-rw-r--r--ecomp-portal-FE/client/app/views/dashboard/dashboard-widget-manage.html152
-rw-r--r--ecomp-portal-FE/client/app/views/dashboard/dashboard-widget.controller.js422
-rw-r--r--ecomp-portal-FE/client/app/views/dashboard/dashboard-widget.controller.less101
-rw-r--r--ecomp-portal-FE/client/app/views/dashboard/dashboard.controller.js312
-rw-r--r--ecomp-portal-FE/client/app/views/dashboard/dashboard.controller.spec.js78
-rw-r--r--ecomp-portal-FE/client/app/views/dashboard/dashboard.less766
-rw-r--r--ecomp-portal-FE/client/app/views/dashboard/dashboard.tpl.html346
-rw-r--r--ecomp-portal-FE/client/app/views/dashboard/newsticker.controller.js47
8 files changed, 2224 insertions, 0 deletions
diff --git a/ecomp-portal-FE/client/app/views/dashboard/dashboard-widget-manage.html b/ecomp-portal-FE/client/app/views/dashboard/dashboard-widget-manage.html
new file mode 100644
index 00000000..84ac2a44
--- /dev/null
+++ b/ecomp-portal-FE/client/app/views/dashboard/dashboard-widget-manage.html
@@ -0,0 +1,152 @@
+<!--
+ ================================================================================
+ 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 style="margin-top: 10px; margin-bottom: 10psx;">
+ <h1 class="heading1"></h1>
+</div>
+<br />
+
+<div style="margin-top: 25px;">
+ <div id="title" class="manage-contactUs-home-manageWidgets-title">Manage {{widgetTypeDisplay}} Widgets</div>
+ <div class="widgets-popup-margin">
+ <div class="get-access-table">
+ <div class="table-control" style="margin:30px;">
+ <div class="c-ecomp-att-abs-table" style="height:300px"">
+ <table att-table id="table-main"
+ table-data="ignoredTableData"
+ current-page="ignoredCurrentPage">
+ <thead att-table-row type="header">
+ <tr>
+ <th id="th-users-1" att-table-header key="title" sortable="true" >Title</th>
+ <th id="th-users-2" att-table-header key="href" sortable="true" >URL</th>
+ <th ng-show="{{widgetType=='EVENTS'}}" id="th-users-3" att-table-header key="event_date" sortable="true" >Date</th>
+ <th ng-show="{{widgetType=='EVENTS'}}" id="th-users-4" att-table-header key="content" sortable="true" >Content</th>
+ <th id="th-users-5" att-table-header key="sortOrder" sortable="true" >Order</th>
+ <th id="th-users-6" att-table-header key="edit" sortable="false" >Edit</th>
+ <th id="th-users-7" att-table-header key="delete" sortable="false" >Delete</th>
+ </tr>
+ </thead>
+ <!-- Use track-by="UNIQUE KEY HERE" or leave out if no unique keys in data -->
+ <tbody att-table-row type="body" class="table-body" track-by="$index" row-repeat="rowData in widgetData">
+ <tr id="tr-rowData" ng-click="">
+ <td att-table-body>
+ <div id="widget-td-title" ng-hide="rowData.showEdit" ng-bind="rowData.title"></div>
+ <input type="text" ng-show="rowData.showEdit" ng-model="widgetData[$index].title"/>
+ </td>
+ <td att-table-body>
+ <div id="widget-td-href" ng-hide="rowData.showEdit" ng-bind="rowData.href"></div>
+ <input type="text" ng-show="rowData.showEdit" ng-model="widgetData[$index].href"/>
+ </td>
+ <td ng-show="{{widgetType=='EVENTS'}}" att-table-body>
+ <div id="widget-td-date" ng-hide="rowData.showEdit" ng-bind="rowData.eventDate"></div>
+ <input type="text" ng-show="rowData.showEdit" ng-model="widgetData[$index].eventDate"/>
+ </td>
+ <td ng-show="{{widgetType=='EVENTS'}}" att-table-body>
+ <div id="widget-td-content" ng-hide="rowData.showEdit">{{rowData.content | cut:true:20:' ...'}}</div>
+ <input type="text" ng-show="rowData.showEdit" ng-model="widgetData[$index].content"/>
+ </td>
+ <td att-table-body>
+ <div id="widget-td-order" ng-hide="rowData.showEdit" ng-bind="rowData.sortOrder"></div>
+ <input type="text" ng-show="rowData.showEdit" ng-model="widgetData[$index].sortOrder"/>
+ </td>
+ <td att-table-body>
+ <div class="delete-contact-us" ng-hide="rowData.showEdit" ng-click="setEdit($index);">
+ <span class="ion-edit"></span>
+ </div>
+ <span ng-show="rowData.showEdit">
+ <a att-button btn-type="primary" ng-click="modify($index);" class="button button--primary" size="small" >Save</a>
+ </span>
+ </td>
+ <td att-table-body>
+ <div class="delete-contact-us" ng-click="remove($index);">
+ <span class="ion-trash-b"></span>
+ </div>
+ </td>
+ </tr>
+ </tbody>
+ </table>
+ </div>
+
+ <div att-divider-lines></div>
+ <div style="margin-top: 15px; margin-left: -80px;" >
+ <form name = "widgetForm" novalidate>
+ <div id="addWidgetHeader" class="contact-us-margin">
+ <h1 style="font-size:18px;">Add</h1>
+ <div class="errMsg">{{errMsg}}</div>
+ <div class="sucessMsg" ng-bind="successMsg"></div>
+ </div>
+ <div id="addWidget" class="contact-us-margin">
+ <div>
+ <div>
+ <div class="add-widget-field">
+ <div id="mots-property-label" class="property-label">Title</div>
+ <input class="input-text-area" type="text" ng-model="newWidgetObject.title" name="title" ng-required="true"/>
+ </div>
+ <div class="add-widget-field">
+ <div class="property-label">URL</div>
+ <input class="input-text-area" type="text" ng-model="newWidgetObject.href" type="url" size="3" name = "url" ng-required = "true"/>
+ </div>
+ <div class="add-widget-field" >
+ <div class="property-label">Sort Order</div>
+ <input class="input-text-area" type="text" ng-model="newWidgetObject.sortOrder"/>
+ </div>
+ </div>
+ <div class="add-widget-field" ng-controller="DatePickerController" ng-show="{{widgetType=='EVENTS'}}">
+ <h4>Event Date</h4>
+ <div>
+ <div>
+ <p class="input-group">
+ <input type="text" name = "eventDate" datetime="yyyy-MM-dd" class="input-text-area" uib-datepicker-popup="{{format}}"
+ ng-model="newWidgetObject.eventDate" is-open="popup1.opened" datepicker-options="dateOptions" close-text="Close" alt-input-formats="altInputFormats"
+ ng-focus="open1()"
+ ng-required = "widgetType =='EVENTS'" />
+ </p>
+ </div>
+ </div>
+ </div>
+
+ <div class="add-contact-us-field-des" ng-show="{{widgetType=='EVENTS'}}">
+ <div class="property-label">Content</div>
+ <textarea style="margin-top: 0px; margin-bottom: 0px; height: 150px" ng-model="newWidgetObject.content" name="content" ng-required = "widgetType =='EVENTS'">
+ </textarea>
+ </div>
+ </div>
+ <div style="height:50px;">
+ <a style="float:right; margin-top:20px;" att-button btn-type="primary" class="button button--primary" size="small" ng-click="saveNew()">Add New</a>
+
+ </div>
+
+ <div att-divider-lines></div>
+
+ </div>
+ </form>
+ </div>
+ <div style="height:50px;">
+ <a style="float:right;" att-button btn-type="primary" class="button button--primary" size="small" ng-click="closeDialog()">Close</a>
+ </div>
+ </div>
+ </div>
+ </div>
+</div>
+
+<script type="application/javascript">
+ $(document).ready(function(){
+ $(".ngdialog-content").css("width","85%")
+ });
+</script>
diff --git a/ecomp-portal-FE/client/app/views/dashboard/dashboard-widget.controller.js b/ecomp-portal-FE/client/app/views/dashboard/dashboard-widget.controller.js
new file mode 100644
index 00000000..d489ac42
--- /dev/null
+++ b/ecomp-portal-FE/client/app/views/dashboard/dashboard-widget.controller.js
@@ -0,0 +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<focusItems.length; i++){
+ if(!isHidden(focusItems[i])){
+ var targetClassName = focusItems[i].className;
+ if(targetClassName!='collapsibleArrow'){
+ focusItems[i].focus();
+ return;
+ }
+ }
+ }
+}
+
+function validateUrl(value){
+ return /^(https?|ftp):\/\/(((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?(((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?)(:\d*)?)(\/((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)?(\?((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(\#((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?$/i.test(value);
+ }
diff --git a/ecomp-portal-FE/client/app/views/dashboard/dashboard-widget.controller.less b/ecomp-portal-FE/client/app/views/dashboard/dashboard-widget.controller.less
new file mode 100644
index 00000000..dda8e300
--- /dev/null
+++ b/ecomp-portal-FE/client/app/views/dashboard/dashboard-widget.controller.less
@@ -0,0 +1,101 @@
+/*-
+ * ================================================================================
+ * 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.
+ * ================================================================================
+ */
+ .searchLiHeader {
+font-weight: bold;
+color: #0574ac;
+font-size: 16px;
+padding-bottom: 10px;
+line-height: 1.5;
+font-family: arial;
+
+}
+
+.searchLiItems{
+cursor: pointer;
+font-weight: normal;
+font-size: 12px;
+color: #444444;
+font-family: arial;
+}
+
+.searchUl {
+list-style: none;
+border-bottom: 1px solid #bbb;
+padding-bottom: 20px;
+}
+
+#editWidgetsContent {
+ height: 300px;
+ width: 1770px;
+}
+
+#editWidgetsContent .scroll-viewport {
+ height: 300px;
+ width: 1770px;
+}
+
+.full button span {
+ background-color: limegreen;
+ border-radius: 32px;
+ color: black;
+}
+
+.partially button span {
+ background-color: orange;
+ border-radius: 32px;
+ color: black;
+ }
+
+ .add-widget-field{
+ width:250px;
+ display: inline-table;
+ margin:10px;
+
+ }
+ .uib-datepicker-popup {
+ th {
+ vertical-align: middle !important;
+ }
+ }
+
+ .input-text-area {
+ font-style: italic;
+ padding: 7px 10px;
+ width: 250px !important;
+ display: inline-block;
+ position: relative;
+ margin-bottom: 10px;
+ border-radius: 6px;
+ border: 1px solid #d8d8d8;
+ height: 32px;
+ border-color: slategrey !important;
+ }
+ .input-inline-edit-text {
+ font-style: italic;
+ padding: 7px 10px;
+ display: inline-block;
+ position: relative;
+ margin-bottom: 10px;
+ border-radius: 6px;
+ border: 1px solid #d8d8d8;
+ height: 32px;
+ border-color: slategrey !important;
+ width:100%;
+ } \ No newline at end of file
diff --git a/ecomp-portal-FE/client/app/views/dashboard/dashboard.controller.js b/ecomp-portal-FE/client/app/views/dashboard/dashboard.controller.js
new file mode 100644
index 00000000..3228f636
--- /dev/null
+++ b/ecomp-portal-FE/client/app/views/dashboard/dashboard.controller.js
@@ -0,0 +1,312 @@
+/*-
+ * ================================================================================
+ * 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(applicationsService, $log,
+ $window, userProfileService, $scope, $cookies, $timeout, $interval,
+ $modal, $state, dashboardService,ngDialog) {
+
+ var _this = this;
+
+ _classCallCheck(this, DashboardCtrl);
+
+ // activate spinner
+ this.isLoading = true;
+ $scope.getUserAppsIsDone = false;
+ this.userProfileService = userProfileService;
+ $scope.demoNum = 1;
+ $scope.event_content_show = false;
+ $scope.widgetData = [];
+
+ $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();
+ }
+ });
+ };
+
+ userProfileService.getUserProfile()
+ .then(
+ function(profile) {
+ // $log.info(profile);
+ $scope.attuid = profile.attuid;
+ // $log.info('user has the following attuid: ' +
+ // profile.attuid);
+ $scope.appsView = [];
+
+ applicationsService.getPersUserApps()
+ .then(
+ function(res) {
+ // $log.info(res);
+ _this.apps = res;
+
+ for (var i = 0; i < _this.apps.length; i++) {
+ $scope.appsView[i] = {
+ sizeX : 2,
+ sizeY : 2,
+ headerText : _this.apps[i].name,
+ subHeaderText : _this.apps[i].notes,
+ imageLink : _this.apps[i].thumbnail || _this.apps[i].imageUrl,
+ order : _this.apps[i].order,
+ restrictedApp : _this.apps[i].restrictedApp,
+ url : _this.apps[i].url
+ };
+ }
+
+ // Append the show add/remove applications tile
+ $scope.appsView[_this.apps.length] = {
+ addRemoveApps : true,
+ sizeX : 2,
+ sizeY : 2,
+ headerText : 'Add/Remove Applications',
+ subHeaderText : '',
+ imageLink : 'assets/images/cloud.png',
+ order : '',
+ restrictedApp : false,
+ url : ''
+ };
+
+ // $log.info('getUserApps apps count : ' +
+ // $scope.appsView.length);
+ // Show 2 rows in the gridster if needed
+ if ($scope.appsView.length > 6) {
+ $(".dashboard-boarder").css({
+ "height" : "400px"
+ });
+ }else{
+ $(".dashboard-boarder").css({
+ "height" : "210px"
+ });
+ }
+ _this.isLoading = false;
+ $scope.getUserAppsIsDone = true;
+ })['catch']
+ (function(err) {
+ $log.error('DashboardCtlr: failed to get applications list', err);
+ _this.isLoading = false;
+ $scope.getUserAppsIsDone = true;
+ });
+ });
+
+
+ /* Widget Gridster Section */
+ $scope.newsGridsterItem = {
+ sizeX : 4,
+ sizeY : 4,
+ headerText : 'News',
+ subHeaderText : '',
+ imageLink : '',
+ order : '',
+ url : ''
+ };
+
+ $scope.eventsGridsterItem = {
+ sizeX : 4,
+ sizeY : 4,
+ headerText : 'Calendar Events',
+ subHeaderText : '',
+ imageLink : '',
+ order : '',
+ url : ''
+ };
+
+ $scope.impoResGridsterItem = {
+ sizeX : 4,
+ sizeY : 4,
+ headerText : 'Resources',
+ subHeaderText : '',
+ imageLink : '',
+ order : '',
+ url : ''
+ };
+ this.gridsterOpts = {
+ columns : 12,
+ colWidth : 95,
+ rowHeight : 95,
+ margins : [ 20, 20 ],
+ outerMargin : true,
+ pushing : true,
+ floating : true,
+ swapping : true,
+ draggable : {
+ handle: 'img'
+ }
+ };
+
+ this.emptyGridsterOpts = {
+ columns : 24,
+ colWidth : 190,
+ rowHeight : 190,
+ margins : [ 20, 20 ],
+ outerMargin : true,
+ pushing : true,
+ floating : true,
+ swapping : true,
+ draggable : {
+ handle: 'img'
+ }
+ };
+
+ this.goToCatalog = function(item) {
+ $state.go('root.appCatalog');
+ }
+
+ // 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 appUrl = null;
+ var urlParts = item.url.split('#');
+ if (urlParts.length < 2)
+ appUrl = item.url + ccParam;
+ 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
+ };
+ $cookies.putObject('addTab', tabContent);
+ }
+ };
+
+ /* News data */
+ $scope.newsData = [];
+ $scope.updateNews = function() {
+ $scope.newsData.length=0;
+ dashboardService.getCommonWidgetData('NEWS').then(function(res) {
+ // $log.info(res.message);
+ var newsDataJsonArray = res.response.items;
+ for (var i = 0; i < newsDataJsonArray.length; i++) {
+ $scope.newsData.push(newsDataJsonArray[i]);
+ }
+ })['catch'](function(err) {
+ $log.error('dashboard controller: failed to get news list', err);
+ _this.isLoading = false;
+ });
+ }
+ $scope.updateNews();
+
+ /* Events data */
+ $scope.eventData = [];
+ $scope.updateEvents = function() {
+ $scope.eventData.length=0;
+ dashboardService.getCommonWidgetData('EVENTS').then(function(res) {
+ var eventDataJsonArray = res.response.items;
+ for (var i = 0; i < eventDataJsonArray.length; i++) {
+ if(eventDataJsonArray[i].eventDate !=null) {
+ // yyyy-mm-dd
+ eventDataJsonArray[i].year = eventDataJsonArray[i].eventDate.substring(2,4);
+ eventDataJsonArray[i].mon = eventDataJsonArray[i].eventDate.substring(5,7);
+ eventDataJsonArray[i].day = eventDataJsonArray[i].eventDate.substring(8,10);
+ }
+ $scope.eventData.push(eventDataJsonArray[i]);
+ }
+ })['catch'](function(err) {
+ $log.error('dashboard controller: failed to get Events list', err);
+ _this.isLoading = false;
+ });
+ }
+ $scope.updateEvents();
+
+ /* Important Resources data */
+ $scope.importResData = [];
+ $scope.updateImportRes = function() {
+ $scope.importResData.length=0;
+ dashboardService.getCommonWidgetData('IMPORTANTRESOURCES').then(
+ function(res) {
+ // $log.error('couldnt get important list...',
+ // res.response.dataBlob);
+ // $log.info(res);
+ var importResDataJSONArray = res.response.items;
+ for (var i = 0; i < importResDataJSONArray.length; i++) {
+ $scope.importResData.push(importResDataJSONArray[i]);
+ }
+ })['catch'](function(err) {
+ $log.error('dashboard controller: failed to get resources list...', err);
+ _this.isLoading = false;
+ });
+ }
+ $scope.updateImportRes();
+
+ if (getParameterByName('noUserError') != null) {
+ if (getParameterByName('noUserError') == "Show") {
+ $("#errorInfo").show();
+ }
+ }
+
+ };
+
+ DashboardCtrl.$inject = [ 'applicationsService', '$log', '$window',
+ 'userProfileService', '$scope', '$cookies', '$timeout',
+ '$interval', '$modal', '$state', 'dashboardService','ngDialog'];
+ 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/client/app/views/dashboard/dashboard.controller.spec.js b/ecomp-portal-FE/client/app/views/dashboard/dashboard.controller.spec.js
new file mode 100644
index 00000000..0a2ddd3a
--- /dev/null
+++ b/ecomp-portal-FE/client/app/views/dashboard/dashboard.controller.spec.js
@@ -0,0 +1,78 @@
+/*-
+ * ================================================================================
+ * 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: DashboardCtrl ', function() {
+ beforeEach(module('ecompApp'));
+
+ let DashboardCtrl, $controller, $q, rootScope, $log, $window, $cookies, scope;
+ let deferredApps, deferredUserProfile, applicationsServiceMock, userProfileServiceMock;
+
+
+ beforeEach(inject( (_$controller_, _$q_, _$rootScope_, _$log_, _$window_, _$cookies_, _CacheFactory_)=>{
+ rootScope = _$rootScope_;
+ scope = rootScope.$new();
+ $q = _$q_;
+ $controller = _$controller_;
+ $log = _$log_;
+ $window = _$window_;
+ $cookies = _$cookies_;
+
+ _CacheFactory_.destroyAll();
+
+ deferredApps = $q.defer();
+ deferredUserProfile = $q.defer();
+ applicationsServiceMock = jasmine.createSpyObj('applicationsServiceMock', ['getUserApps']);
+ applicationsServiceMock.getUserApps.and.returnValue(deferredApps.promise);
+
+ userProfileServiceMock = jasmine.createSpyObj('userProfileServiceMock',['getUserProfile']);
+ userProfileServiceMock.getUserProfile.and.returnValue(deferredUserProfile.promise);
+
+ DashboardCtrl = $controller('DashboardCtrl', {
+ applicationsService: applicationsServiceMock,
+ $log: $log,
+ $window: $window,
+ userProfileService: userProfileServiceMock,
+ $scope: scope,
+ $cookies: $cookies
+ });
+ scope.$digest();
+ }));
+
+ it('should populate this.apps with data from portals service getUserApps', inject(function ( _$q_) {
+ $q = _$q_;
+
+ let profile = {roles: 'superAdmin', userId: 'userid'};
+
+ deferredUserProfile.resolve(profile)
+ deferredApps.resolve([{name: 'portal1'},{name: 'portal2'},{name: 'portal3'}]);
+ scope.$digest();
+ expect(scope.appsViewData.length).toBe(3);
+ }));
+
+ it('should call $log error when getAllPortals fail', inject(function ( _$q_) {
+ $q = _$q_;
+ spyOn($log, 'error');
+ deferredUserProfile.reject('something happened!');
+ scope.$digest();
+ expect($log.error).toHaveBeenCalled();
+ }));
+
+});
diff --git a/ecomp-portal-FE/client/app/views/dashboard/dashboard.less b/ecomp-portal-FE/client/app/views/dashboard/dashboard.less
new file mode 100644
index 00000000..4dc1a6c8
--- /dev/null
+++ b/ecomp-portal-FE/client/app/views/dashboard/dashboard.less
@@ -0,0 +1,766 @@
+/*-
+ * ================================================================================
+ * 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.
+ * ================================================================================
+ */
+ .w-ecomp-applications-home {
+ .bg_w;
+ 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;
+ }
+
+ .go-button {
+ .btn-green;
+ width: 96px;
+ position: absolute;
+ border-radius: 0px;
+ }
+
+ .applications-home-container {
+ .content_justify;
+ position: relative;
+ padding: 15px 0 32px 0;
+ width: 100%;
+
+ .applications-home-title {
+ .a24r;
+ margin: auto;
+ .content_justify;
+ }
+ .portals-list {
+ min-height: 70vh;
+ //display: flex;
+ justify-content: center;
+ flex-flow: row wrap;
+ width: 1170px;
+
+ margin: auto;
+ margin-bottom: 63px;
+
+ .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 {
+ .a24r;
+ margin-bottom: 4px;
+
+ text-overflow: ellipsis;
+ overflow: hidden;
+ }
+ .info-description {
+ .c16r;
+ 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{
+ .o14r;
+ position: absolute;
+ width: 100%;
+ line-height: 1.5em;
+}
+.w-ecomp-main-disclaimer {
+ text-align: center;
+ .o14r;
+ //position: absolute;
+ bottom: -75px;
+ line-height: 1.5em;
+ margin: 0 auto;
+ width:1170px;
+ position: relative;
+
+}
+.build-number {
+ .o12i;
+}
+
+@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{
+ 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: 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;
+}
+
+
+.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;
+}
+
+
+
+
+* {margin: 0; padding: 0;}
+body {background: #ccc;}
+
+.slider{
+ width: 640px;
+ position: relative;
+ padding-top: 320px;
+
+ margin: 50px auto;
+
+ box-shadow: 0 10px 20px -5px rgba(0, 0, 0, 0.75);
+}
+
+.slider>img{
+ position: absolute;
+ left: 0; top: 0;
+ transition: all 0.5s;
+}
+
+.slider input[name='slide_switch'] {
+ display: none;
+}
+
+.slider label {
+ margin: 18px 0 0 18px;
+ border: 3px solid #999;
+
+ float: left;
+ cursor: pointer;
+ transition: all 0.5s;
+
+ opacity: 0.6;
+}
+
+.slider label img{
+ display: block;
+}
+
+.slider input[name='slide_switch']:checked+label {
+ border-color: #666;
+ opacity: 1;
+}
+
+.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);
+}
+
+.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: arial;
+}
+.events-link{
+ color: #067ab4 !important;
+}
+
+
+
+/*widgets*/
+.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;
+ 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: 5px;
+ 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;
+}
+
+@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;
+ border-radius: 4px;
+ padding: 3px;
+ -webkit-user-select: none;
+
+}
+
+
+
+.news ul {
+ float: left;
+ width:100%;
+ -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;
+
+ /* font-family: arial;*/
+}
+
+.news ul:hover { animation-play-state: paused }
+.news span:hover+ul { animation-play-state: paused }
+.resources {
+
+ width: 350px;
+ 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;
+}
+
+
+.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 }
+
+
+.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;
+}
+.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{
+ /*margin-top:25px;*/
+}
+.information-section-gridsterContent{
+ height:300px;
+}
+.information-sections-gridster-header{
+ color: #0574ac;
+ font-family: arial;
+ font-size: 25px;
+
+}
+/*application empty div*/
+.app-error-block {
+ padding-top: 10px;
+
+}
+.activity-error-block {
+ padding-top: 60px;
+
+}
+
+.activity-error-msg1{
+ text-align: center;
+ margin-top: 20px;
+ font-family: 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; }
+
+.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;
+}
+
+.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: 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;
+} \ No newline at end of file
diff --git a/ecomp-portal-FE/client/app/views/dashboard/dashboard.tpl.html b/ecomp-portal-FE/client/app/views/dashboard/dashboard.tpl.html
new file mode 100644
index 00000000..0d96a585
--- /dev/null
+++ b/ecomp-portal-FE/client/app/views/dashboard/dashboard.tpl.html
@@ -0,0 +1,346 @@
+<!--
+ ================================================================================
+ 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="w-ecomp-applications-home" id="contentId">
+ <div class="applications-home-container">
+ <div align="center" id="errorInfo"
+ style="display: none; font-size: 12px; margin-left: 5px">
+ <span style="color: red">You don't have a user account in that
+ application. Please ask the system administrator. </span>
+ </div>
+ <div class="portals-list" style="margin-bottom: 0px;">
+ <div>
+ <div class="simulateGridHeader">
+ <span class="simulateGridHeaderTitle">Applications</span>
+ </div>
+ <div class="dashboard-boarder">
+ <div class="gridster-container override_background">
+
+ <div att-gridster att-gridster-options="dashboard.gridsterOpts">
+
+ <div ng-if="appsView.length==1">
+ <i class="ion-information-circled full-linear-ion-information-circled"
+ style="margin-left: 50%; font-size: 90px; color: black"></i> <br>
+ <div class="activity-error-msg1">
+ <span>Click on the tile at the left to personalize your applications.</span>
+ </div>
+ </div>
+
+ <div class="style_prevu_kit" att-gridster-item='item'
+ ng-repeat="item in appsView"
+ id="app-{{item.headerText.split(' ').join('-')}}">
+ <!-- A regular application tile -->
+ <div class="grider-content-ecomp" ng-if="item.addRemoveApps == null">
+ <div id="grips-{{item.headerText.split(' ').join('-')}}"
+ ng-hide="users.isLoadingTable && !users.getUserAppsIsDone"
+ att-gridster-item-header
+ grips-img-path="assets/images/grips.png"
+ header-text="{{item.headerText | elipsis: 33}}"
+ class="app-gridster-header"></div>
+ <div id="app-image-{{item.headerText.split(' ').join('-')}}"
+ att-gridster-item-body
+ ng-style="{'cursor':'pointer',
+ 'background-image': 'url('+(item.imageLink)+')',
+ 'order': item.order,
+ 'background-color':'white',
+ 'background-repeat': 'no-repeat',
+ 'background-size': '170px 130px'}"
+ ng-click="dashboard.goToPortal(item)"
+ ng-hide="users.isLoadingTable && !users.getUserAppsIsDone"
+ class="gridsterContent"></div>
+ </div>
+ <!-- Format the special tile differently -->
+ <div class="grider-content-ecomp" style="width: 170px" ng-if="item.addRemoveApps">
+ <div id="grips-add-remove-applications-tile" att-gridster-item-header
+ grips-img-path="assets/images/grips.png"
+ header-text='Select applications..'
+ ng-click="dashboard.goToCatalog()"
+ ng-style="{'cursor':'pointer'}"
+ class="app-gridster-header">
+ </div>
+ <div id="app-image-empty" att-gridster-item-body
+ ng-style="{'cursor':'pointer',
+ 'text-align':'center',
+ 'order': item.order,
+ 'background-color':'white',
+ 'background-repeat': 'no-repeat',
+ 'background-size': '170px 130px',
+ 'width': '170px',
+ 'height': '120px',
+ 'opacity': '1'}"
+ ng-click="dashboard.goToCatalog()" class="gridsterContent">
+ <label style="font-size:12px">Click here to personalize <br> this applications page</label>
+ <i class="ion-plus-circled" style="font-size:70px;color: #067ab4"></i>
+ </div>
+ </div>
+ </div>
+
+ </div>
+
+ </div>
+
+ </div>
+ </div>
+
+ <br>
+ <br>
+
+ <div class="information-section">
+ <div id="news-gridster-container"
+ class="gridster-container override_background">
+ <div att-gridster att-gridster-options="dashboard.gridsterOpts">
+
+ <div class="style_prevu_kit">
+ <!-- News -->
+ <div att-gridster-item='newsGridsterItem'>
+ <div att-gridster-item-header
+ grips-img-path="assets/images/grips.png"
+ header-text="{{newsGridsterItem.headerText | elipsis: 33}}"
+ header-icon="full-linear-icon-webwindow"
+ sub-header-text="{{newsGridsterItem.subHeaderText | elipsis: 56}}"
+ class="information-sections-gridster-header"
+ style="font-size: 18px">
+
+ <div ng-if="isAdminPortalAdmin == true"
+ style="font-size: 20px;">
+
+ <a id="widgetHeaderBtns"
+ class="widgetHeaderBtn widgetHeaderBtnPosition singleBtnBorder"
+ ng-mousedown="showNewsOption=!showNewsOption"
+ ng-mouseleave="showNewsOption=false"
+ ng-class="singleBtnBorder" role="button" alt="Settings"
+ title="Settings" att-accessibility-click="13,32" tabindex="0">
+ <span class="ion-more" style="color:#888"></span>
+ </a>
+ <ul class="optionsMenu"
+ style="max-width: 130px; height: 32px; display: block"
+ ng-show="showNewsOption" ng-mouseenter="showNewsOption=true"
+ ng-mouseleave="showNewsOption=false">
+ <!-- ngIf: widget.duplicateAllowed -->
+ <li ng-click="editWidgetModalPopup(newsData, 'NEWS');"
+ ddh-accessibility-click="13,32"><a
+ class="optionsMenuLink" href="javascript:void(0)">Edit</a></li>
+ <!-- end ngIf: widget.duplicateAllowed -->
+
+ </ul>
+ </div>
+
+ </div>
+ <div id="newsContainer" att-gridster-item-body
+ class="information-section-gridsterContent">
+ <div class="news">
+ <ul id="newsContent" ng-show="newsData.length!=0">
+ <li ng-repeat="news in newsData"><a href="{{news.href}}"
+ target="_blank" ng-bind="news.title"></a></li>
+ </ul>
+ <div ng-hide="newsData.length!=0">
+ <div class="activity-error-container"
+ style="background: rgb(255, 255, 255); overflow: auto !important; width: 100%;">
+ <div class="activity-error-block">
+ <i class="ion-information-circled full-linear-ion-information-circled"
+ style="margin-left: 125px; font-size: 90px"></i> <br>
+ <div class="activity-error-msg1">There's currently no
+ news available.</div>
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+ <!-- Events -->
+ <div att-gridster-item='eventsGridsterItem'>
+ <div att-gridster-item-header
+ grips-img-path="assets/images/grips.png"
+ header-text="{{eventsGridsterItem.headerText | elipsis: 33}}"
+ header-icon="full-linear-icon-calendar"
+ sub-header-text="{{eventsGridsterItem.subHeaderText | elipsis: 56}}"
+ class="information-sections-gridster-header"
+ style="font-size: 18px">
+ <div style="font-size: 20px;"
+ ng-if="isAdminPortalAdmin == true" class="ng-scope"
+ role="button" tabindex="0">
+ <a id="widgetHeaderBtns"
+ class="widgetHeaderBtn widgetHeaderBtnPosition singleBtnBorder"
+ ng-mousedown="showEventsOption=!showEventsOption"
+ ng-mouseleave="showEventsOption=false"
+ ng-class="singleBtnBorder" role="button" alt="Settings"
+ title="Settings" att-accessibility-click="13,32" tabindex="0">
+ <span class="ion-more" style="color:#888"></span>
+ </a>
+ <ul class="optionsMenu"
+ style="max-width: 130px; height: 32px; display: block"
+ ng-show="showEventsOption"
+ ng-mouseenter="showEventsOption=true"
+ ng-mouseleave="showEventsOption=false">
+ <!-- ngIf: widget.duplicateAllowed -->
+ <li ng-click="editWidgetModalPopup(eventData, 'EVENTS');">
+ <a class="optionsMenuLink" href="javascript:void(0)"
+ ddh-accessibility-click="13,32">Edit</a>
+ </li>
+ <!-- end ngIf: widget.duplicateAllowed -->
+ </ul>
+ </div>
+ </div>
+ <div att-gridster-item-body
+ class="information-section-gridsterContent">
+ <div class="events">
+ <ul ng-show="eventData.length!=0">
+ <li ng-repeat="event in eventData">
+ <div ng-click="event_content_show=!event_content_show">
+ <div class="events-date">{{event.mon}}/{{event.day}}/{{event.year}}
+ </div>
+ <div>
+ <div class="event-title-div">
+ <p ng-bind="event.title"></p>
+ </div>
+ <div>
+ <span class="ion-ios-arrow-up" ng-if="event_content_show"
+ style="color: #888; font-size: 22px;"></span> <span
+ class="ion-ios-arrow-down" ng-if="!event_content_show"
+ style="color: #888; font-size: 22px;"></span>
+
+ </div>
+ <div style="clear: both;"></div>
+ </div>
+ </div>
+ <div class="events-content" ng-show="event_content_show">
+ <div class="events-content-body">
+ <a class="events-link" ng-href="{{event.href}}"
+ target="_blank"> <span ng-bind="event.content"></span>
+ </a>
+ </div>
+ <div></div>
+ </div>
+ </li>
+
+
+ </ul>
+ <div ng-hide="eventData.length!=0">
+ <div class="activity-error-container"
+ style="background: rgb(255, 255, 255); overflow: hidden !important; width: 100%;">
+ <div class="activity-error-block">
+ <i class="ion-information-circled full-linear-ion-information-circled"
+ style="margin-left: 125px; font-size: 90px"></i> <br>
+ <div class="activity-error-msg1">There's currently no
+ event available.</div>
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+
+ <!-- Important Resources -->
+ <div att-gridster-item='impoResGridsterItem'>
+ <div att-gridster-item-header
+ grips-img-path="assets/images/grips.png"
+ header-text="{{impoResGridsterItem.headerText | elipsis: 33}}"
+ header-icon="full-linear-icon-cloud"
+ sub-header-text="{{impoResGridsterItem.subHeaderText | elipsis: 56}}"
+ class="information-sections-gridster-header"
+ style="font-size: 18px">
+ <!-- <span class="full-linear-icon-cloud" style="font-size: 33px; font-weight: bold; margin-right: 10px;"></span>
+ -->
+ <div style="font-size: 20px;"
+ ng-if="isAdminPortalAdmin == true" class="ng-scope"
+ role="button" tabindex="0">
+ <a id="widgetHeaderBtns"
+ class="widgetHeaderBtn widgetHeaderBtnPosition singleBtnBorder"
+ ng-class="singleBtnBorder" role="button" alt="Settings"
+ ng-mousedown="showImpResOption=!showImpResOption"
+ ng-mouseleave="showImpResOption=false" title="Settings"
+ att-accessibility-click="13,32" tabindex="0"> <span
+ class="ion-more" style="color:#888"></span>
+ </a>
+
+ <ul class="optionsMenu"
+ style="max-width: 130px; height: 32px; display: block"
+ ng-show="showImpResOption"
+ ng-mouseenter="showImpResOption=true"
+ ng-mouseleave="showImpResOption=false">
+ <!-- ngIf: widget.duplicateAllowed -->
+ <li
+ ng-click="editWidgetModalPopup(importResData, 'IMPORTANTRESOURCES');">
+ <a class="optionsMenuLink" href="javascript:void(0)"
+ ddh-accessibility-click="13,32">Edit</a>
+ </li>
+ <!-- end ngIf: widget.duplicateAllowed -->
+
+ </ul>
+ </div>
+ </div>
+ <div att-gridster-item-body
+ class="information-section-gridsterContent">
+ <div class="resources">
+ <ul ng-show="importResData.length!=0">
+
+ <li ng-repeat="item in importResData"><a
+ href="{{item.href}}" target="_blanl">{{item.title}}</a></li>
+ </ul>
+ <div ng-hide="importResData.length!=0">
+ <div class="activity-error-container"
+ style="background: rgb(255, 255, 255); overflow: hidden !important; width: 100%;">
+ <div class="activity-error-block">
+ <i class="ion-information-circled full-linear-ion-information-circled"
+ style="margin-left: 125px; font-size: 90px"></i> <br>
+ <div class="activity-error-msg1">There's currently no
+ links available.</div>
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+
+ <div class="style_prevu_kit" att-gridster-item='item'
+ ng-repeat="item in widgetData">
+ <div>
+ <div att-gridster-item-header
+ grips-img-path="assets/images/grips.png"
+ header-text="{{item.headerText | elipsis: 33}}"
+ sub-header-text="{{item.subHeaderText | elipsis: 56}}"
+ class="app-gridster-header"></div>
+ <div att-gridster-item-body></div>
+ </div>
+
+ </div>
+
+ <div class="style_prevu_kit" att-gridster-item='item'
+ ng-repeat="item in widgetData">
+ <div>
+ <div att-gridster-item-header
+ grips-img-path="assets/images/grips.png"
+ header-text="{{item.headerText | elipsis: 33}}"
+ sub-header-text="{{item.subHeaderText | elipsis: 56}}"
+ class="app-gridster-header"></div>
+ <div att-gridster-item-body></div>
+ </div>
+
+ </div>
+ </div>
+ </div>
+ </div>
+
+ <div></div>
+
+ </div>
+
+ </div>
+</div> \ No newline at end of file
diff --git a/ecomp-portal-FE/client/app/views/dashboard/newsticker.controller.js b/ecomp-portal-FE/client/app/views/dashboard/newsticker.controller.js
new file mode 100644
index 00000000..88e6942e
--- /dev/null
+++ b/ecomp-portal-FE/client/app/views/dashboard/newsticker.controller.js
@@ -0,0 +1,47 @@
+/*-
+ * ================================================================================
+ * 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 NewsTickerController {
+ constructor($scope) {
+ $scope.newstape = function(){
+ jQuery('.newstape').newstape({
+
+ period: 30,
+
+ offset: 1,
+
+ mousewheel: true,
+
+ mousewheelRate: 30,
+
+ dragable: true,
+
+ heightSpy: true
+
+ });
+ };
+ $scope.newstape();
+
+ }
+ }
+ NewsTickerController.$inject = ['$scope'];
+ angular.module('ecompApp').controller('NewsTickerController', NewsTickerController);
+})();