From 7ca173de3de046501d79164da0c8c8871a03089b Mon Sep 17 00:00:00 2001 From: Trygve Laugstøl Date: Sat, 5 Mar 2016 16:47:32 +0100 Subject: web: o Adding an API method to get per-hour aggregate values. Doesn't use the by_hour table yet. o Adding a simple line graph component that can graph a single property's value. --- web/static/app/diller/web.js | 236 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 236 insertions(+) create mode 100644 web/static/app/diller/web.js (limited to 'web/static/app/diller/web.js') diff --git a/web/static/app/diller/web.js b/web/static/app/diller/web.js new file mode 100644 index 0000000..4b173ad --- /dev/null +++ b/web/static/app/diller/web.js @@ -0,0 +1,236 @@ +(function () { + var isoFormat = 'YYYY-MM-DDTHH:mm:ss'; + + function FrontPageController(devices) { + var ctrl = this; + + ctrl.devices = devices.data.devices; + } + + function DeviceController($uibModal, device, DillerRpc) { + var ctrl = this; + + ctrl.device = device.data.device; + + ctrl.propertyChunks = _(ctrl.device.properties).sortByAll(['name', 'key']).chunk(3).value(); + + ctrl.editDeviceAttribute = function (attributeName) { + var outer = ctrl; + $uibModal.open({ + controller: function ($uibModalInstance) { + var ctrl = this; + + ctrl.title = 'Edit device ' + attributeName; + ctrl.label = attributeName.substr(0, 1).toUpperCase() + attributeName.substr(1); + ctrl.value = outer.device[attributeName]; + + ctrl.update = function () { + DillerRpc.patchDevice(outer.device.id, {attribute: attributeName, value: ctrl.value}) + .then(function (res) { + outer.device = res.data.device; + $uibModalInstance.close({}); + }, function (res) { + ctrl.error = res.data.message; + }); + }; + }, + controllerAs: 'ctrl', + bindToController: true, + templateUrl: 'app/templates/edit-attribute.modal.html' + }); + } + } + + function PropertyController($timeout, $route, $uibModal, DillerRpc, device, values) { + var ctrl = this; + + function updateData(device) { + ctrl.device = device.data.device; + ctrl.property = _.find(ctrl.device.properties, {id: $route.current.params.propertyId}); + } + updateData(device); + ctrl.values = values.data.values; + + var refreshPromise; + ctrl.refresh = function () { + $timeout.cancel(refreshPromise); + refreshPromise = $timeout(function () { + ctrl.loading = true; + }, 200); + + DillerRpc.getValues($route.current.params.propertyId).then(function (res) { + ctrl.values = res.data.values; + ctrl.loading = false; + $timeout.cancel(refreshPromise); + }) + }; + + ctrl.editPropertyAttribute = function (attributeName) { + var outer = ctrl; + $uibModal.open({ + controller: function ($uibModalInstance) { + var ctrl = this; + + ctrl.title = 'Edit property ' + attributeName; + ctrl.label = attributeName.substr(0, 1).toUpperCase() + attributeName.substr(1); + ctrl.value = outer.property[attributeName]; + + ctrl.update = function () { + DillerRpc.patchProperty(outer.property.id, {attribute: attributeName, value: ctrl.value}) + .then(function (res) { + updateData(res); + $uibModalInstance.close({}); + }, function (res) { + ctrl.error = res.data.message; + }); + }; + }, + controllerAs: 'ctrl', + bindToController: true, + templateUrl: 'app/templates/edit-attribute.modal.html' + }); + }; + + ctrl.interval = Diller.Interval.hours(5); + + // ctrl.values24h = values24h.data.values; + + function chartist() { + var avgs = _.pluck(ctrl.values24h, 'avg'); + var timestamps = _.map(ctrl.values24h, function(row) { + var m = moment(row.timestamp, isoFormat); + return m.format('HH:mm'); + }); + + var data = { + labels: timestamps, + series: [ + avgs + ] + }; + + var options = { + axisX: { + showLabel: false, + showGrid: false + } + }; + +// options.lineSmooth = Chartist.Interpolation.cardinal({ +// fillHoles: true, +// }) + + options.axisX = { + showLabel: true, + showGrid: true, + labelInterpolationFnc: function(value, index) { + return index % 4 === 0 ? value : null; + } + }; + + var chartData = { + series: [[]], + labels: [] + }; + + // var chart = new Chartist.Line('#values-chart', chartData, options); + // console.log('chart', chart); +/* + $timeout(function() { + chartData = data; + // console.log(data); + var chart = new Chartist.Line('#values-chart', chartData, options); + console.log('chart', chart); + }); +*/ + } + + // chartist(); + } + + function TimestampFilter() { + return function (value) { + if (!value) { + return; + } + + return moment(value).startOf('second').fromNow(); + } + } + + function DlTimestampDirective() { + return { + restrict: 'E', + scope: { + value: '=' + }, + replace: true, + template: '{{value|timestamp}}' + }; + } + + function DlDotsDirective() { + return { + restrict: 'E', + scope: { + value: '=' + }, + replace: true, + template: '...\n' + }; + } + + function config($routeProvider) { + $routeProvider + .when('/', { + controller: FrontPageController, + controllerAs: 'ctrl', + templateUrl: 'app/templates/front-page.html', + resolve: { + devices: DillerRpcResolve.getDevices + } + }) + .when('/device/:deviceId', { + controller: DeviceController, + controllerAs: 'ctrl', + templateUrl: 'app/templates/device.html', + resolve: { + device: DillerRpcResolve.getDevice + } + }) + .when('/device/:deviceId/property/:propertyId', { + controller: PropertyController, + controllerAs: 'ctrl', + templateUrl: 'app/templates/property.html', + resolve: { + device: DillerRpcResolve.getDevice, + values: DillerRpcResolve.getValues + } + }) + .otherwise({ + redirectTo: '/' + }); + } + + function run($log) { + window.console = $log; + } + + function DillerConfig() { + var head = document.getElementsByTagName('head')[0]; + var base = head.getElementsByTagName('base')[0]; + var baseUrl = base.href.replace(/\/$/, ''); + return { + baseUrl: baseUrl + }; + } + + angular + .module('diller.web', ['ngRoute', 'ui.bootstrap', 'diller.line-chart']) + .config(config) + .run(run) + .filter('timestamp', TimestampFilter) + .directive('dlTimestamp', DlTimestampDirective) + .directive('dlDots', DlDotsDirective) + .service('DillerConfig', DillerConfig); +})(); -- cgit v1.2.3