update sensor page
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
.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 @@
};
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>