diff options
| author | Ed Tanous <ed.tanous@intel.com> | 2017-06-28 09:43:09 -0700 |
|---|---|---|
| committer | Ed Tanous <ed.tanous@intel.com> | 2017-06-28 09:43:09 -0700 |
| commit | 5fceeb4563c08468e9623cef1e3d7f4de9373d2f (patch) | |
| tree | 6854993a288f126465e6bd3b089e7090aef7409e /static | |
| parent | 7b4e3dae0477703143b8cb28b3a6abc9d4d0d83b (diff) | |
| download | bmcweb-5fceeb4563c08468e9623cef1e3d7f4de9373d2f.tar.gz bmcweb-5fceeb4563c08468e9623cef1e3d7f4de9373d2f.zip | |
update sensor page
Diffstat (limited to 'static')
| -rw-r--r-- | static/CMakeLists.txt | 9 | ||||
| -rw-r--r-- | static/index.html | 34 | ||||
| -rw-r--r-- | static/js/bmcApp.js | 15 | ||||
| -rw-r--r-- | static/js/sensorController.js | 71 | ||||
| -rw-r--r-- | static/js/smart-table.js | 534 | ||||
| -rw-r--r-- | static/partial-sensor.html | 38 |
6 files changed, 656 insertions, 45 deletions
diff --git a/static/CMakeLists.txt b/static/CMakeLists.txt index 4e6831c..6e5bc2b 100644 --- a/static/CMakeLists.txt +++ b/static/CMakeLists.txt @@ -19,6 +19,7 @@ set(JAVASCRIPT_ASSETS js/run_prettify.js js/angular.js js/angular-ui-router-uib-modal.js + js/smart-table.js noVNC/core/inflator.js noVNC/core/input/xtscancodes.js @@ -72,6 +73,8 @@ set(MINIFIED_ASSETS_OUT "") find_program(UGLIFY_MINIFIER uglifyjs) if(NOT UGLIFY_MINIFIER) message("uglifyjs not found") +else() + message("Found ${UGLIFY_MINIFIER}") endif() foreach(JAVASCRIPT_ASSET ${JAVASCRIPT_ASSETS}) @@ -81,7 +84,7 @@ foreach(JAVASCRIPT_ASSET ${JAVASCRIPT_ASSETS}) file(MAKE_DIRECTORY "${FOLDERNAME}") if(UGLIFY_MINIFIER) add_custom_command(OUTPUT ${MINIFIED_FILENAME} - COMMAND uglifyjs --compress --mangle + COMMAND ${UGLIFY_MINIFIER} --compress --mangle --output "${MINIFIED_FILENAME}" "${CMAKE_CURRENT_SOURCE_DIR}/${JAVASCRIPT_ASSET}" DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/${JAVASCRIPT_ASSET}" @@ -102,6 +105,8 @@ endforeach(JAVASCRIPT_ASSET) find_program(CSS_MINIFIER cssnano) if(NOT CSS_MINIFIER) message("cssnano not found") +else() + message("Found ${CSS_MINIFIER}") endif() # for now CSS is included as is foreach(CSS_ASSET ${CSS_ASSETS}) @@ -110,7 +115,7 @@ foreach(CSS_ASSET ${CSS_ASSETS}) file(MAKE_DIRECTORY "${FOLDERNAME}") if(CSS_MINIFIER) add_custom_command(OUTPUT ${MINIFIED_FILENAME} - COMMAND cssnano + COMMAND ${CSS_MINIFIER} "${CMAKE_CURRENT_SOURCE_DIR}/${CSS_ASSET}" "${CMAKE_CURRENT_BINARY_DIR}/${CSS_ASSET}" diff --git a/static/index.html b/static/index.html index 6e5f9bd..61e779b 100644 --- a/static/index.html +++ b/static/index.html @@ -22,6 +22,8 @@ <script type="text/javascript" src="static/js/angular-ui-router-uib-modal.js" defer></script> <script type="text/javascript" src="static/js/lodash.core.js" defer></script> + <script type="text/javascript" src="static/js/smart-table.js" defer></script> + <script type="text/javascript" src="static/js/ui-bootstrap-tpls-2.5.0.js" defer></script> <script type="text/javascript" src="static/js/bmcApp.js" defer></script> @@ -54,6 +56,38 @@ </head> <body ng-controller="MainCtrl" ng-class="(is_logged_in()) ? '' : 'auth-main'"> + <main ng-if="$pageFinishedLoading" ng-class="{ 'menu-collapsed': $baSidebarService.isMenuCollapsed() }"> + + <ba-sidebar></ba-sidebar> + <page-top></page-top> + + <div class="al-main"> + <div class="al-content"> + <content-top></content-top> + <div ui-view autoscroll="true" autoscroll-body-top></div> + </div> + </div> + + <footer class="al-footer clearfix"> + <div class="al-footer-right">Created with <i class="ion-heart"></i></div> + <div class="al-footer-main clearfix"> + <div class="al-copy">Blur Admin 2016</div> + <ul class="al-share clearfix"> + <li><i class="socicon socicon-facebook"></i></li> + <li><i class="socicon socicon-twitter"></i></li> + <li><i class="socicon socicon-google"></i></li> + <li><i class="socicon socicon-github"></i></li> + </ul> + </div> + </footer> + + <back-top></back-top> + </main> + + <div id="preloader" ng-show="!$pageFinishedLoading"> + <div></div> + </div> + <div> <nav class="navbar navbar-inverse" ng-if='is_logged_in()'> <div class="container-fluid"> diff --git a/static/js/bmcApp.js b/static/js/bmcApp.js index 55e4a42..1812261 100644 --- a/static/js/bmcApp.js +++ b/static/js/bmcApp.js @@ -1,8 +1,15 @@ 'use strict'; angular.module('Authentication', []); var app = angular.module('bmcApp', [ - 'ngCookies', 'ngAnimate', 'ngSanitize', 'ui.bootstrap', - 'ui.router', 'ngWebSocket', 'Authentication', 'ui.router.modal', + 'ngCookies', + 'ngAnimate', + 'ngSanitize', + 'ui.bootstrap', + 'ui.router', + 'ngWebSocket', + 'Authentication', + 'ui.router.modal', + 'smart-table', ]); app.service('loginInterceptor', [ @@ -128,7 +135,7 @@ app.config([ .state('fwupdate.confirm', { url : '/confirm', templateUrl : 'static/partial-fwupdateconfirm.html', - modal: true + modal : true }) // ABOUT PAGE AND MULTIPLE NAMED VIEWS ================================= .state('about', @@ -216,7 +223,7 @@ angular.module('Authentication').factory('AuthenticationService', [ }; service.IsLoggedIn = function() { - if ($rootScope.globals['currentUser']){ + if ($rootScope.globals['currentUser']) { return true; } else { return false; diff --git a/static/js/sensorController.js b/static/js/sensorController.js index 67c9d82..0fa9045 100644 --- a/static/js/sensorController.js +++ b/static/js/sensorController.js @@ -1,41 +1,54 @@ angular.module('bmcApp').controller('sensorController', [ '$scope', '$http', '$location', 'websocketService', function($scope, $http, $location, websocketService) { - $scope.sensor_values = {}; + $scope.smartTablePageSize = 10; + $scope.next_id = 0; + websocketService.start('/sensorws', function(evt) { + var obj = JSON.parse(evt.data); - var host = $location.host(); - var port = $location.port(); - var protocol = "ws://"; - if ($location.protocol() === 'https') { - protocol = 'wss://'; - } - websocketService.start(protocol + host + ":" + port + "/sensorws", function (evt) { - var obj = JSON.parse(evt.data); - $scope.$apply(function () { - for (var key in obj) { - if (obj.hasOwnProperty(key)) { - console.log(key + " -> " + obj[key]); - $scope.sensor_values[key] = obj[key]; - } + $scope.$apply(function() { + for (var sensor_name in obj) { + var found = false; + for (var sensor_index in $scope.rowCollection) { + var sensor_object = $scope.rowCollection[sensor_index]; + if (sensor_object.name === sensor_name) { + sensor_object.value = obj[sensor_name]; + found = true; + break; + } } - }); + if (!found) { + console.log(sensor_name + ' -> ' + obj[sensor_name]); + $scope.next_id = $scope.next_id + 1; + + $scope.rowCollection.push({ + id : $scope.next_id, + name : sensor_name, + value : obj[sensor_name], + }); + } + }; + }); }); + $scope.rowCollection = []; + } ]); -app.factory('websocketService', function () { - return { - start: function (url, callback) { - var websocket = new WebSocket(url); - websocket.onopen = function () { - }; - websocket.onclose = function () { - }; - websocket.onmessage = function (evt) { - callback(evt); - }; - } +app.factory('websocketService', function($location) { + return { + start: function(url, callback) { + var host = $location.host(); + var port = 18080; + var protocol = 'wss://'; + if ($location.protocol() === 'http') { + protocol = 'ws://'; } + var websocket = new WebSocket(protocol + host + ':' + port + url); + websocket.onopen = function() {}; + websocket.onclose = function() {}; + websocket.onmessage = function(evt) { callback(evt); }; } -);
\ No newline at end of file + } +});
\ No newline at end of file diff --git a/static/js/smart-table.js b/static/js/smart-table.js new file mode 100644 index 0000000..e0246d4 --- /dev/null +++ b/static/js/smart-table.js @@ -0,0 +1,534 @@ +/** +* @version 2.1.8 +* @license MIT +*/ +(function (ng, undefined){ + 'use strict'; + +ng.module('smart-table', []).run(['$templateCache', function ($templateCache) { + $templateCache.put('template/smart-table/pagination.html', + '<nav ng-if="numPages && pages.length >= 2"><ul class="pagination">' + + '<li ng-repeat="page in pages" ng-class="{active: page==currentPage}"><a href="javascript: void(0);" ng-click="selectPage(page)">{{page}}</a></li>' + + '</ul></nav>'); +}]); + + +ng.module('smart-table') + .constant('stConfig', { + pagination: { + template: 'template/smart-table/pagination.html', + itemsByPage: 10, + displayedPages: 5 + }, + search: { + delay: 400, // ms + inputEvent: 'input' + }, + select: { + mode: 'single', + selectedClass: 'st-selected' + }, + sort: { + ascentClass: 'st-sort-ascent', + descentClass: 'st-sort-descent', + descendingFirst: false, + skipNatural: false, + delay:300 + }, + pipe: { + delay: 100 //ms + } + }); +ng.module('smart-table') + .controller('stTableController', ['$scope', '$parse', '$filter', '$attrs', function StTableController ($scope, $parse, $filter, $attrs) { + var propertyName = $attrs.stTable; + var displayGetter = $parse(propertyName); + var displaySetter = displayGetter.assign; + var safeGetter; + var orderBy = $filter('orderBy'); + var filter = $filter('filter'); + var safeCopy = copyRefs(displayGetter($scope)); + var tableState = { + sort: {}, + search: {}, + pagination: { + start: 0, + totalItemCount: 0 + } + }; + var filtered; + var pipeAfterSafeCopy = true; + var ctrl = this; + var lastSelected; + + function copyRefs (src) { + return src ? [].concat(src) : []; + } + + function updateSafeCopy () { + safeCopy = copyRefs(safeGetter($scope)); + if (pipeAfterSafeCopy === true) { + ctrl.pipe(); + } + } + + function deepDelete (object, path) { + if (path.indexOf('.') != -1) { + var partials = path.split('.'); + var key = partials.pop(); + var parentPath = partials.join('.'); + var parentObject = $parse(parentPath)(object) + delete parentObject[key]; + if (Object.keys(parentObject).length == 0) { + deepDelete(object, parentPath); + } + } else { + delete object[path]; + } + } + + if ($attrs.stSafeSrc) { + safeGetter = $parse($attrs.stSafeSrc); + $scope.$watch(function () { + var safeSrc = safeGetter($scope); + return safeSrc && safeSrc.length ? safeSrc[0] : undefined; + }, function (newValue, oldValue) { + if (newValue !== oldValue) { + updateSafeCopy(); + } + }); + $scope.$watch(function () { + var safeSrc = safeGetter($scope); + return safeSrc ? safeSrc.length : 0; + }, function (newValue, oldValue) { + if (newValue !== safeCopy.length) { + updateSafeCopy(); + } + }); + $scope.$watch(function () { + return safeGetter($scope); + }, function (newValue, oldValue) { + if (newValue !== oldValue) { + tableState.pagination.start = 0; + updateSafeCopy(); + } + }); + } + + /** + * sort the rows + * @param {Function | String} predicate - function or string which will be used as predicate for the sorting + * @param [reverse] - if you want to reverse the order + */ + this.sortBy = function sortBy (predicate, reverse) { + tableState.sort.predicate = predicate; + tableState.sort.reverse = reverse === true; + + if (ng.isFunction(predicate)) { + tableState.sort.functionName = predicate.name; + } else { + delete tableState.sort.functionName; + } + + tableState.pagination.start = 0; + return this.pipe(); + }; + + /** + * search matching rows + * @param {String} input - the input string + * @param {String} [predicate] - the property name against you want to check the match, otherwise it will search on all properties + */ + this.search = function search (input, predicate) { + var predicateObject = tableState.search.predicateObject || {}; + var prop = predicate ? predicate : '$'; + + input = ng.isString(input) ? input.trim() : input; + $parse(prop).assign(predicateObject, input); + // to avoid to filter out null value + if (!input) { + deepDelete(predicateObject, prop); + } + tableState.search.predicateObject = predicateObject; + tableState.pagination.start = 0; + return this.pipe(); + }; + + /** + * this will chain the operations of sorting and filtering based on the current table state (sort options, filtering, ect) + */ + this.pipe = function pipe () { + var pagination = tableState.pagination; + var output; + filtered = tableState.search.predicateObject ? filter(safeCopy, tableState.search.predicateObject) : safeCopy; + if (tableState.sort.predicate) { + filtered = orderBy(filtered, tableState.sort.predicate, tableState.sort.reverse); + } + pagination.totalItemCount = filtered.length; + if (pagination.number !== undefined) { + pagination.numberOfPages = filtered.length > 0 ? Math.ceil(filtered.length / pagination.number) : 1; + pagination.start = pagination.start >= filtered.length ? (pagination.numberOfPages - 1) * pagination.number : pagination.start; + output = filtered.slice(pagination.start, pagination.start + parseInt(pagination.number)); + } + displaySetter($scope, output || filtered); + }; + + /** + * select a dataRow (it will add the attribute isSelected to the row object) + * @param {Object} row - the row to select + * @param {String} [mode] - "single" or "multiple" (multiple by default) + */ + this.select = function select (row, mode) { + var rows = copyRefs(displayGetter($scope)); + var index = rows.indexOf(row); + if (index !== -1) { + if (mode === 'single') { + row.isSelected = row.isSelected !== true; + if (lastSelected) { + lastSelected.isSelected = false; + } + lastSelected = row.isSelected === true ? row : undefined; + } else { + rows[index].isSelected = !rows[index].isSelected; + } + } + }; + + /** + * take a slice of the current sorted/filtered collection (pagination) + * + * @param {Number} start - start index of the slice + * @param {Number} number - the number of item in the slice + */ + this.slice = function splice (start, number) { + tableState.pagination.start = start; + tableState.pagination.number = number; + return this.pipe(); + }; + + /** + * return the current state of the table + * @returns {{sort: {}, search: {}, pagination: {start: number}}} + */ + this.tableState = function getTableState () { + return tableState; + }; + + this.getFilteredCollection = function getFilteredCollection () { + return filtered || safeCopy; + }; + + /** + * Use a different filter function than the angular FilterFilter + * @param filterName the name under which the custom filter is registered + */ + this.setFilterFunction = function setFilterFunction (filterName) { + filter = $filter(filterName); + }; + + /** + * Use a different function than the angular orderBy + * @param sortFunctionName the name under which the custom order function is registered + */ + this.setSortFunction = function setSortFunction (sortFunctionName) { + orderBy = $filter(sortFunctionName); + }; + + /** + * Usually when the safe copy is updated the pipe function is called. + * Calling this method will prevent it, which is something required when using a custom pipe function + */ + this.preventPipeOnWatch = function preventPipe () { + pipeAfterSafeCopy = false; + }; + }]) + .directive('stTable', function () { + return { + restrict: 'A', + controller: 'stTableController', + link: function (scope, element, attr, ctrl) { + + if (attr.stSetFilter) { + ctrl.setFilterFunction(attr.stSetFilter); + } + + if (attr.stSetSort) { + ctrl.setSortFunction(attr.stSetSort); + } + } + }; + }); + +ng.module('smart-table') + .directive('stSearch', ['stConfig', '$timeout','$parse', function (stConfig, $timeout, $parse) { + return { + require: '^stTable', + link: function (scope, element, attr, ctrl) { + var tableCtrl = ctrl; + var promise = null; + var throttle = attr.stDelay || stConfig.search.delay; + var event = attr.stInputEvent || stConfig.search.inputEvent; + + attr.$observe('stSearch', function (newValue, oldValue) { + var input = element[0].value; + if (newValue !== oldValue && input) { + ctrl.tableState().search = {}; + tableCtrl.search(input, newValue); + } + }); + + //table state -> view + scope.$watch(function () { + return ctrl.tableState().search; + }, function (newValue, oldValue) { + var predicateExpression = attr.stSearch || '$'; + if (newValue.predicateObject && $parse(predicateExpression)(newValue.predicateObject) !== element[0].value) { + element[0].value = $parse(predicateExpression)(newValue.predicateObject) || ''; + } + }, true); + + // view -> table state + element.bind(event, function (evt) { + evt = evt.originalEvent || evt; + if (promise !== null) { + $timeout.cancel(promise); + } + + promise = $timeout(function () { + tableCtrl.search(evt.target.value, attr.stSearch || ''); + promise = null; + }, throttle); + }); + } + }; + }]); + +ng.module('smart-table') + .directive('stSelectRow', ['stConfig', function (stConfig) { + return { + restrict: 'A', + require: '^stTable', + scope: { + row: '=stSelectRow' + }, + link: function (scope, element, attr, ctrl) { + var mode = attr.stSelectMode || stConfig.select.mode; + element.bind('click', function () { + scope.$apply(function () { + ctrl.select(scope.row, mode); + }); + }); + + scope.$watch('row.isSelected', function (newValue) { + if (newValue === true) { + element.addClass(stConfig.select.selectedClass); + } else { + element.removeClass(stConfig.select.selectedClass); + } + }); + } + }; + }]); + +ng.module('smart-table') + .directive('stSort', ['stConfig', '$parse', '$timeout', function (stConfig, $parse, $timeout) { + return { + restrict: 'A', + require: '^stTable', + link: function (scope, element, attr, ctrl) { + + var predicate = attr.stSort; + var getter = $parse(predicate); + var index = 0; + var classAscent = attr.stClassAscent || stConfig.sort.ascentClass; + var classDescent = attr.stClassDescent || stConfig.sort.descentClass; + var stateClasses = [classAscent, classDescent]; + var sortDefault; + var skipNatural = attr.stSkipNatural !== undefined ? attr.stSkipNatural : stConfig.sort.skipNatural; + var descendingFirst = attr.stDescendingFirst !== undefined ? attr.stDescendingFirst : stConfig.sort.descendingFirst; + var promise = null; + var throttle = attr.stDelay || stConfig.sort.delay; + + if (attr.stSortDefault) { + sortDefault = scope.$eval(attr.stSortDefault) !== undefined ? scope.$eval(attr.stSortDefault) : attr.stSortDefault; + } + + //view --> table state + function sort () { + if (descendingFirst) { + index = index === 0 ? 2 : index - 1; + } else { + index++; + } + + var func; + predicate = ng.isFunction(getter(scope)) || ng.isArray(getter(scope)) ? getter(scope) : attr.stSort; + if (index % 3 === 0 && !!skipNatural !== true) { + //manual reset + index = 0; + ctrl.tableState().sort = {}; + ctrl.tableState().pagination.start = 0; + func = ctrl.pipe.bind(ctrl); + } else { + func = ctrl.sortBy.bind(ctrl, predicate, index % 2 === 0); + } + if (promise !== null) { + $timeout.cancel(promise); + } + if (throttle < 0) { + func(); + } else { + promise = $timeout(func, throttle); + } + } + + element.bind('click', function sortClick () { + if (predicate) { + scope.$apply(sort); + } + }); + + if (sortDefault) { + index = sortDefault === 'reverse' ? 1 : 0; + sort(); + } + + //table state --> view + scope.$watch(function () { + return ctrl.tableState().sort; + }, function (newValue) { + if (newValue.predicate !== predicate) { + index = 0; + element + .removeClass(classAscent) + .removeClass(classDescent); + } else { + index = newValue.reverse === true ? 2 : 1; + element + .removeClass(stateClasses[index % 2]) + .addClass(stateClasses[index - 1]); + } + }, true); + } + }; + }]); + +ng.module('smart-table') + .directive('stPagination', ['stConfig', function (stConfig) { + return { + restrict: 'EA', + require: '^stTable', + scope: { + stItemsByPage: '=?', + stDisplayedPages: '=?', + stPageChange: '&' + }, + templateUrl: function (element, attrs) { + if (attrs.stTemplate) { + return attrs.stTemplate; + } + return stConfig.pagination.template; + }, + link: function (scope, element, attrs, ctrl) { + + scope.stItemsByPage = scope.stItemsByPage ? +(scope.stItemsByPage) : stConfig.pagination.itemsByPage; + scope.stDisplayedPages = scope.stDisplayedPages ? +(scope.stDisplayedPages) : stConfig.pagination.displayedPages; + + scope.currentPage = 1; + scope.pages = []; + + function redraw () { + var paginationState = ctrl.tableState().pagination; + var start = 1; + var end; + var i; + var prevPage = scope.currentPage; + scope.totalItemCount = paginationState.totalItemCount; + scope.currentPage = Math.floor(paginationState.start / paginationState.number) + 1; + + start = Math.max(start, scope.currentPage - Math.abs(Math.floor(scope.stDisplayedPages / 2))); + end = start + scope.stDisplayedPages; + + if (end > paginationState.numberOfPages) { + end = paginationState.numberOfPages + 1; + start = Math.max(1, end - scope.stDisplayedPages); + } + + scope.pages = []; + scope.numPages = paginationState.numberOfPages; + + for (i = start; i < end; i++) { + scope.pages.push(i); + } + + if (prevPage !== scope.currentPage) { + scope.stPageChange({newPage: scope.currentPage}); + } + } + + //table state --> view + scope.$watch(function () { + return ctrl.tableState().pagination; + }, redraw, true); + + //scope --> table state (--> view) + scope.$watch('stItemsByPage', function (newValue, oldValue) { + if (newValue !== oldValue) { + scope.selectPage(1); + } + }); + + scope.$watch('stDisplayedPages', redraw); + + //view -> table state + scope.selectPage = function (page) { + if (page > 0 && page <= scope.numPages) { + ctrl.slice((page - 1) * scope.stItemsByPage, scope.stItemsByPage); + } + }; + + if (!ctrl.tableState().pagination.number) { + ctrl.slice(0, scope.stItemsByPage); + } + } + }; + }]); + +ng.module('smart-table') + .directive('stPipe', ['stConfig', '$timeout', function (config, $timeout) { + return { + require: 'stTable', + scope: { + stPipe: '=' + }, + link: { + + pre: function (scope, element, attrs, ctrl) { + + var pipePromise = null; + + if (ng.isFunction(scope.stPipe)) { + ctrl.preventPipeOnWatch(); + ctrl.pipe = function () { + + if (pipePromise !== null) { + $timeout.cancel(pipePromise) + } + + pipePromise = $timeout(function () { + scope.stPipe(ctrl.tableState(), ctrl); + }, config.pipe.delay); + + return pipePromise; + } + } + }, + + post: function (scope, element, attrs, ctrl) { + ctrl.pipe(); + } + } + }; + }]); + +})(angular);
\ No newline at end of file diff --git a/static/partial-sensor.html b/static/partial-sensor.html index 3486a63..4503312 100644 --- a/static/partial-sensor.html +++ b/static/partial-sensor.html @@ -1,25 +1,43 @@ <div class="container" ng-controller="sensorController"> <div class="row"> - <div class="col-lg-8"> + <div class="col-md-12"> <div class="box box-primary"> <div class="box-header with-border"> <h4>Summary - <h4> - </div> - <div class="box-body"> - <table class="table table-striped system-status-table"> + </h4> + <div class="pull-right"> + <select class="form-control show-tick" title="Rows on page" selectpicker ng-model="smartTablePageSize" ng-options="i for i in [5,10,25,50,100,500]"> + </select> + </div> + <div class="horizontal-scroll box-body"> </div> + + <table class="table table-striped system-status-table" st-table="smartTableData" st-safe-src="rowCollection"> <thead> + <tr class="sortable "> + <th class="table-id" st-sort="id" st-sort-default="true">#</th> + <th st-sort="name">Name</th> + <th st-sort="value">Value</th> + </tr> <tr> - <th>Sensor</th> - <th>Value</th> + <th></th> + <th><input st-search="name" placeholder="Search Name" class="input-sm form-control search-input" type="search" /></th> + <th><input st-search="value" placeholder="Search Value" class="input-sm form-control search-input" type="search" /></th> </tr> </thead> <tbody> - <tr ng-animate="'animate'" ng-repeat="(sensor_name, value) in sensor_values"> - <td class="fit">{{ sensor_name }}</td> - <td class="fit">{{ value }}</td> + <tr ng-repeat="item in smartTableData"> + <td class="table-id">{{item.id}}</td> + <td>{{item.name}}</td> + <td>{{item.value}}</td> </tr> </tbody> + <tfoot> + <tr> + <td colspan="6" class="text-center"> + <div st-pagination="" st-items-by-page="smartTablePageSize" st-displayed-pages="7"></div> + </td> + </tr> + </tfoot> </table> </div> </div> |

