aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTrygve Laugstøl <trygvis@inamo.no>2015-10-25 00:33:41 +0200
committerTrygve Laugstøl <trygvis@inamo.no>2015-10-25 01:47:52 +0200
commite8ec4001ce1297d5a3db6d3fc8af8de47daa6a61 (patch)
tree839d9c1da0c2b1db539c104d9aacc8c8e62a3dcd
parent0266bdd60cb9cccf20a5ded3eba72ea833bee72d (diff)
downloaddiller-server-e8ec4001ce1297d5a3db6d3fc8af8de47daa6a61.tar.gz
diller-server-e8ec4001ce1297d5a3db6d3fc8af8de47daa6a61.tar.bz2
diller-server-e8ec4001ce1297d5a3db6d3fc8af8de47daa6a61.tar.xz
diller-server-e8ec4001ce1297d5a3db6d3fc8af8de47daa6a61.zip
wip
-rw-r--r--.bowerrc2
-rw-r--r--.gitignore6
-rw-r--r--diller-web.js12
-rw-r--r--package.json1
-rw-r--r--src/Diller.js3
-rw-r--r--src/DillerConfig.js1
-rw-r--r--src/DillerDao.js8
-rw-r--r--src/web/DillerWeb.js83
-rw-r--r--web/app/templates/device.html21
-rw-r--r--web/index.html24
-rw-r--r--web/static/app/DillerRpc.js (renamed from web/app/DillerRpc.js)10
-rw-r--r--web/static/app/app.css3
-rw-r--r--web/static/app/app.js (renamed from web/app/app.js)18
-rw-r--r--web/static/app/templates/device.html34
-rw-r--r--web/static/app/templates/front-page.html (renamed from web/app/templates/front-page.html)11
-rw-r--r--web/static/app/templates/property.html (renamed from web/app/templates/property.html)6
-rw-r--r--web/templates/index.jade52
-rw-r--r--web/templates/wat.html25
18 files changed, 222 insertions, 98 deletions
diff --git a/.bowerrc b/.bowerrc
index 80e4029..4c64c6a 100644
--- a/.bowerrc
+++ b/.bowerrc
@@ -1,3 +1,3 @@
{
- "directory": "web/bower_components"
+ "directory": "web/static/bower_components"
}
diff --git a/.gitignore b/.gitignore
index 7603995..d1026a4 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,7 @@
.idea
+*.iml
+
node_modules
-web/bower_components
+bower_components
+
+*.pg
diff --git a/diller-web.js b/diller-web.js
index 4cceaa1..f89755f 100644
--- a/diller-web.js
+++ b/diller-web.js
@@ -1,3 +1,4 @@
+var fs = require('fs');
var di = require('di');
var injector = new di.Injector();
@@ -6,5 +7,14 @@ config.configureLogging('web');
var dillerWeb = injector.get(require('./src/web/DillerWeb'));
dillerWeb.init();
-dillerWeb.generateRpc();
+
+if (config.updateDillerRpc) {
+ var DillerRpc = dillerWeb.generateRpc();
+ var orig = fs.readFileSync('web/static/app/DillerRpc.js', {encoding: 'utf-8'});
+ if (orig != DillerRpc) {
+ console.log('DillerRpc updated');
+ fs.writeFileSync('web/static/app/DillerRpc.js', DillerRpc);
+ }
+}
+
dillerWeb.listen();
diff --git a/package.json b/package.json
index bfc0373..6f822ad 100644
--- a/package.json
+++ b/package.json
@@ -14,6 +14,7 @@
"db-migrate": "^0.9.23",
"di": "^2.0.0-pre-14",
"express": "^4.13.3",
+ "jade": "^1.11.0",
"lodash": "^3.10.1",
"mqtt": "^1.4.3",
"pg": "^4.4.2",
diff --git a/src/Diller.js b/src/Diller.js
index a057054..fa2e308 100644
--- a/src/Diller.js
+++ b/src/Diller.js
@@ -81,7 +81,7 @@ function Diller(config, db) {
}
if (!f) {
- log.warn('Unknown message topic:', topic);
+ log.warn('Unknown topic:', topic);
return;
}
@@ -107,6 +107,7 @@ function Diller(config, db) {
});
})
.then(function (data) {
+ // log.info('data.device', data.device, 'data.property', data.property);
return f(dao, data.device, data.property, message.toString());
});
}).then(function (res) {
diff --git a/src/DillerConfig.js b/src/DillerConfig.js
index 84afe42..652561a 100644
--- a/src/DillerConfig.js
+++ b/src/DillerConfig.js
@@ -55,6 +55,7 @@ function configureLogging(app) {
function DillerConfig() {
return {
isProd: isProd,
+ updateDillerRpc: !isProd(),
mqttUrl: mqttUrl,
postgresqlConfig: postgresqlConfig,
configureLogging: configureLogging,
diff --git a/src/DillerDao.js b/src/DillerDao.js
index c4d0e67..b46e734 100644
--- a/src/DillerDao.js
+++ b/src/DillerDao.js
@@ -33,7 +33,7 @@ function DillerDao(tx) {
}
function devicePropertyByDeviceIdAndKey(deviceId, key) {
- return tx.oneOrNone('SELECT id FROM device_property WHERE device=$1 AND key=$2', [deviceId, key]);
+ return tx.oneOrNone('SELECT ' + propertyColumns + ' FROM device_property WHERE device=$1 AND key=$2', [deviceId, key]);
}
function devicePropertiesByDeviceId(deviceId) {
@@ -41,11 +41,11 @@ function DillerDao(tx) {
}
function insertDeviceProperty(deviceId, key) {
- return tx.oneOrNone('INSERT INTO device_property(id, device, key, created_timestamp) VALUES(DEFAULT, $1, $2, CURRENT_TIMESTAMP) RETURNING ' + propertyColumns, [deviceId, key]);
+ return tx.one('INSERT INTO device_property(id, device, key, created_timestamp) VALUES(DEFAULT, $1, $2, CURRENT_TIMESTAMP) RETURNING ' + propertyColumns, [deviceId, key]);
}
function updatePropertyName(id, name) {
- return tx.none('UPDATE device_property SET name=$1 WHERE id=$2', name, id);
+ return tx.none('UPDATE device_property SET name=$1 WHERE id=$2', [name, id]);
}
function updatePropertyDescription(id, description) {
@@ -58,7 +58,7 @@ function DillerDao(tx) {
function valuesByPropertyId(propertyId, limit) {
limit = limit || 10;
- return tx.many('SELECT timestamp, value FROM value WHERE property=$1 LIMIT $2', [propertyId, limit]);
+ return tx.many('SELECT timestamp, value FROM value WHERE property=$1 ORDER BY timestamp DESC LIMIT $2', [propertyId, limit]);
}
function insertValue(propertyId, value) {
diff --git a/src/web/DillerWeb.js b/src/web/DillerWeb.js
index 40fbc3d..a5bdf6b 100644
--- a/src/web/DillerWeb.js
+++ b/src/web/DillerWeb.js
@@ -59,17 +59,22 @@ function DillerWeb(diller, db, config) {
});
}
+ function getIndex(req, res) {
+ var baseUrl = (req.headers['trygvis-prefix'] || '').replace(/\/$/, '');
+ res.render('index', {baseUrl: baseUrl + '/'});
+ }
+
function init() {
app = express();
app.use(bodyParser.urlencoded({extended: true}));
app.use(bodyParser.json());
- var router = express.Router();
+ var api = express.Router();
- function addRoute(name, method, path, callback) {
- router[method](path, callback);
- var layer = _.last(router.stack);
+ function addApi(name, method, path, callback) {
+ api[method](path, callback);
+ var layer = _.last(api.stack);
calls.push({
name: name,
@@ -82,12 +87,21 @@ function DillerWeb(diller, db, config) {
});
}
- addRoute('getDevices', 'get', '/device', getDevices);
- addRoute('getDevice', 'get', '/device/:deviceId', getDevice);
- addRoute('getValues', 'get', '/property/:propertyId/values', getValues);
+ addApi('getDevices', 'get', '/device', getDevices);
+ addApi('getDevice', 'get', '/device/:deviceId', getDevice);
+ addApi('getValues', 'get', '/property/:propertyId/values', getValues);
+
+ var templates = express.Router();
- app.use('/api', router);
- app.use(express.static('web'));
+ templates.get('/', getIndex);
+
+ app.set('views', 'web/templates');
+ app.set('view engine', 'jade');
+ app.set('view cache', false);
+
+ app.use('/api', api);
+ app.use('/', templates);
+ app.use(express.static('web/static'));
}
function listen() {
@@ -96,54 +110,59 @@ function DillerWeb(diller, db, config) {
}
function generateRpc() {
- console.log('function DillerRpc($http) {');
+ var s =
+ 'function DillerRpc($http, DillerConfig) {\n' +
+ ' var baseUrl = DillerConfig.baseUrl;\n' +
+ '\n';
- var s = _.map(calls, function (call) {
+ s += _.map(calls, function (call) {
//console.error(call);
- console.error('call.layer', call.layer);
+ //console.error('call.layer', call.layer);
var s = ' function ' + call.name + '(' + call.keys.join(', ') + ') {\n' +
' var req = {};\n' +
' req.method = \'' + call.method + '\';\n' +
- ' req.url = \'/api' + call.path + '\';\n';
+ ' req.url = baseUrl + \'/api' + call.path + '\';\n';
s += _.map(call.layer.keys, function (key) {
return ' req.url = req.url.replace(/:' + key.name + '/, ' + key.name + ');\n'
- }).join('');
+ }).join('\n');
s +=
' return $http(req);\n' +
' }\n';
return s;
- });
- _.each(s, function (x) {
- console.log(x);
- });
-
- console.log(' return {');
- console.log(_.map(calls, function (call) {
+ }).join('\n');
+ s += '\n';
+ s += ' return {\n';
+ s += _.map(calls, function (call) {
return ' ' + call.name + ': ' + call.name
- }).join(',\n'));
- console.log(' };');
- console.log('}');
- console.log('');
-
- console.log('DillerRpcResolve = {};');
- _.each(calls, function (call) {
+ }).join(',\n');
+ s += '\n';
+ s += ' };\n';
+ s += '}\n';
+ s += '\n';
+
+ s += 'DillerRpcResolve = {};\n';
+ s += _.map(calls, function (call) {
+ var s = '';
var args = ['DillerRpc'];
if (call.keys.length > 0) {
args.push('$route');
}
- console.log('DillerRpcResolve.' + call.name + ' = function(' + args.join(', ') + ') {');
+ s += 'DillerRpcResolve.' + call.name + ' = function(' + args.join(', ') + ') {\n';
args = _.map(call.keys, function (key) {
return '$route.current.params.' + key;
});
- console.log(' return DillerRpc.' + call.name + '(' + args.join(', ') + ');');
- console.log('};');
- });
+ s += ' return DillerRpc.' + call.name + '(' + args.join(', ') + ');\n';
+ s += '};\n';
+
+ return s;
+ }).join('');
+ return s;
}
return {
diff --git a/web/app/templates/device.html b/web/app/templates/device.html
deleted file mode 100644
index ae028b5..0000000
--- a/web/app/templates/device.html
+++ /dev/null
@@ -1,21 +0,0 @@
-<div class="container">
-
- <h1>
- {{ctrl.device.key}}
- <small class="text-muted">device</small>
- </h1>
-
- <ul>
- <li>Created: {{ctrl.device.created_timestamp | date}}</li>
- <li>Name: {{ctrl.property.name}}</li>
- <li>Description: {{ctrl.property.description}}</li>
- </ul>
-
- <h3>Properties</h3>
-
- <ul>
- <li ng-repeat="p in ctrl.device.properties | orderBy:'key'">
- <a href="#/device/{{ctrl.device.id}}/property/{{p.id}}">{{p.key}}</a>
- </li>
- </ul>
-</div>
diff --git a/web/index.html b/web/index.html
deleted file mode 100644
index b591e55..0000000
--- a/web/index.html
+++ /dev/null
@@ -1,24 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
-<head>
- <meta charset="utf-8">
- <meta name="viewport" content="width=device-width, initial-scale=1">
- <meta http-equiv="x-ua-compatible" content="ie=edge">
-
- <script src="bower_components/jquery/dist/jquery.js" type="application/javascript"></script>
-
- <script src="bower_components/bootstrap/dist/js/bootstrap.js" type="application/javascript"></script>
- <link rel="stylesheet" href="bower_components/bootstrap/dist/css/bootstrap.css"/>
-
- <script src="bower_components/angular/angular.js" type="application/javascript"></script>
- <script src="bower_components/angular-route/angular-route.js" type="application/javascript"></script>
- <script src="bower_components/lodash/lodash.js" type="application/javascript"></script>
-
- <script src="app/DillerRpc.js" type="application/javascript"></script>
- <script src="app/app.js" type="application/javascript"></script>
- <base href="/">
-</head>
-<body ng-app="Diller" ng-view>
-Loading Diller ...
-</body>
-</html>
diff --git a/web/app/DillerRpc.js b/web/static/app/DillerRpc.js
index a0c20fb..de90aee 100644
--- a/web/app/DillerRpc.js
+++ b/web/static/app/DillerRpc.js
@@ -1,15 +1,17 @@
-function DillerRpc($http) {
+function DillerRpc($http, DillerConfig) {
+ var baseUrl = DillerConfig.baseUrl;
+
function getDevices() {
var req = {};
req.method = 'get';
- req.url = '/api/device';
+ req.url = baseUrl + '/api/device';
return $http(req);
}
function getDevice(deviceId) {
var req = {};
req.method = 'get';
- req.url = '/api/device/:deviceId';
+ req.url = baseUrl + '/api/device/:deviceId';
req.url = req.url.replace(/:deviceId/, deviceId);
return $http(req);
}
@@ -17,7 +19,7 @@ function DillerRpc($http) {
function getValues(propertyId) {
var req = {};
req.method = 'get';
- req.url = '/api/property/:propertyId/values';
+ req.url = baseUrl + '/api/property/:propertyId/values';
req.url = req.url.replace(/:propertyId/, propertyId);
return $http(req);
}
diff --git a/web/static/app/app.css b/web/static/app/app.css
new file mode 100644
index 0000000..090ac5e
--- /dev/null
+++ b/web/static/app/app.css
@@ -0,0 +1,3 @@
+nav.navbar {
+ margin-bottom: 2rem;
+}
diff --git a/web/app/app.js b/web/static/app/app.js
index cd14ae5..5274362 100644
--- a/web/app/app.js
+++ b/web/static/app/app.js
@@ -24,7 +24,7 @@
.when('/', {
controller: FrontPageController,
controllerAs: 'ctrl',
- templateUrl: '/app/templates/front-page.html',
+ templateUrl: 'app/templates/front-page.html',
resolve: {
devices: DillerRpcResolve.getDevices
}
@@ -32,7 +32,7 @@
.when('/device/:deviceId', {
controller: DeviceController,
controllerAs: 'ctrl',
- templateUrl: '/app/templates/device.html',
+ templateUrl: 'app/templates/device.html',
resolve: {
device: DillerRpcResolve.getDevice
}
@@ -40,7 +40,7 @@
.when('/device/:deviceId/property/:propertyId', {
controller: PropertyController,
controllerAs: 'ctrl',
- templateUrl: '/app/templates/property.html',
+ templateUrl: 'app/templates/property.html',
resolve: {
device: DillerRpcResolve.getDevice,
values: DillerRpcResolve.getValues
@@ -53,8 +53,20 @@
//$locationProvider.html5Mode(true);
}
+ function DillerConfig() {
+ var head = document.getElementsByTagName('head')[0];
+ var base = head.getElementsByTagName('base')[0];
+ console.log('base =', base);
+ var baseUrl = base.href.replace(/\/$/, '');
+ console.log('baseUrl =', baseUrl);
+ return {
+ baseUrl: baseUrl
+ };
+ }
+
angular
.module('Diller', ['ngRoute'])
.config(config)
+ .service('DillerConfig', DillerConfig)
.service('DillerRpc', DillerRpc);
})();
diff --git a/web/static/app/templates/device.html b/web/static/app/templates/device.html
new file mode 100644
index 0000000..b466fdc
--- /dev/null
+++ b/web/static/app/templates/device.html
@@ -0,0 +1,34 @@
+<div class="container">
+
+ <h1>
+ {{ctrl.device.key}}
+ <small class="text-muted">device</small>
+ </h1>
+
+ <ul>
+ <li>Created: {{ctrl.device.created_timestamp | date}}</li>
+ <li>Name: {{ctrl.property.name}}</li>
+ <li>Description: {{ctrl.property.description}}</li>
+ </ul>
+
+ <h3>Properties</h3>
+
+ <table class="table">
+ <thead>
+ <tr>
+ <td>Registered</td>
+ <td>Key</td>
+ </tr>
+ </thead>
+ <tbody>
+ <tr ng-repeat="p in ctrl.device.properties | orderBy:'key'">
+ <td>
+ {{p.created_timestamp | date:'medium'}}
+ </td>
+ <td>
+ <a href="#/device/{{ctrl.device.id}}/property/{{p.id}}">{{p.key}}</a>
+ </td>
+ </tr>
+ </tbody>
+ </table>
+</div>
diff --git a/web/app/templates/front-page.html b/web/static/app/templates/front-page.html
index 1846dea..68026c3 100644
--- a/web/app/templates/front-page.html
+++ b/web/static/app/templates/front-page.html
@@ -1,21 +1,20 @@
<div class="container">
- <h1>
- Diller
- <small class="text-muted">All your sensor data are belong to us</small>
- </h1>
-
<h2>Devices</h2>
- <table>
+ <table class="table">
<thead>
<tr>
+ <th>Registered</th>
<th>Key</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="d in ctrl.devices | orderBy:'key'">
<td>
+ {{d.created_timestamp | date:'medium'}}
+ </td>
+ <td>
<a href="#/device/{{d.id}}">{{d.key}}</a>
</td>
</tr>
diff --git a/web/app/templates/property.html b/web/static/app/templates/property.html
index 65a66e8..5f925e7 100644
--- a/web/app/templates/property.html
+++ b/web/static/app/templates/property.html
@@ -31,6 +31,12 @@
<td>{{v.value}}</td>
</tr>
</tbody>
+ <tbody>
+ <tr ng-repeat="v in ctrl.values">
+ <td>{{v.timestamp | date:'medium'}}</td>
+ <td>{{v.value}}</td>
+ </tr>
+ </tbody>
</table>
</div>
diff --git a/web/templates/index.jade b/web/templates/index.jade
new file mode 100644
index 0000000..025354e
--- /dev/null
+++ b/web/templates/index.jade
@@ -0,0 +1,52 @@
+doctype html
+
+html(lang='en')
+ head
+ meta(charset='utf-8')
+ meta(name="viewport", content="width=device-width, initial-scale=1")
+ meta(http-equiv="x-ua-compatible", content="ie=edge")
+
+ base(href!=baseUrl)
+
+ script(src="bower_components/jquery/dist/jquery.js", type="application/javascript")
+ script(src="bower_components/bootstrap/dist/js/bootstrap.js", type="application/javascript")
+ link(rel="stylesheet", href="bower_components/bootstrap/dist/css/bootstrap.css")
+ script(src="bower_components/angular/angular.js", type="application/javascript")
+ script(src="bower_components/angular-route/angular-route.js", type="application/javascript")
+ script(src="bower_components/lodash/lodash.js", type="application/javascript")
+
+ script(src="app/DillerRpc.js", type="application/javascript")
+ script(src="app/app.js", type="application/javascript")
+ link(href="app/app.css", rel="stylesheet")
+
+ body(ng-app="Diller")
+ .container
+ nav.navbar.navbar-dark.bg-inverse
+ a.navbar-brand(href='#/') Diller
+ ul.nav.navbar-nav
+ li.nav-item
+ a.nav-link(href='#/') Devices
+
+ //
+ <nav class="navbar navbar-light bg-faded">
+ <a class="navbar-brand" href="#">Navbar</a>
+ <ul class="nav navbar-nav">
+ <li class="nav-item active">
+ <a class="nav-link" href="#">Home <span class="sr-only">(current)</span></a>
+ </li>
+ <li class="nav-item">
+ <a class="nav-link" href="#">Features</a>
+ </li>
+ <li class="nav-item">
+ <a class="nav-link" href="#">Pricing</a>
+ </li>
+ <li class="nav-item">
+ <a class="nav-link" href="#">About</a>
+ </li>
+ </ul>
+ <form class="form-inline navbar-form pull-right">
+ <input class="form-control" type="text" placeholder="Search">
+ <button class="btn btn-success-outline" type="submit">Search</button>
+ </form>
+ </nav>
+ span(ng-view) Loading Diller ...
diff --git a/web/templates/wat.html b/web/templates/wat.html
new file mode 100644
index 0000000..fd504a7
--- /dev/null
+++ b/web/templates/wat.html
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <meta charset="utf-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1">
+ <meta http-equiv="x-ua-compatible" content="ie=edge">
+ <base href="/diller/">
+
+ <base href="/">
+ <script src="./bower_components/jquery/dist/jquery.js" type="application/javascript"></script>
+
+ <script src="./bower_components/bootstrap/dist/js/bootstrap.js" type="application/javascript"></script>
+ <link rel="stylesheet" href="./bower_components/bootstrap/dist/css/bootstrap.css"/>
+
+ <script src="./bower_components/angular/angular.js" type="application/javascript"></script>
+ <script src="./bower_components/angular-route/angular-route.js" type="application/javascript"></script>
+ <script src="./bower_components/lodash/lodash.js" type="application/javascript"></script>
+
+ <script src="../static/app/DillerRpc.js" type="application/javascript"></script>
+ <script src="../static/app/app.js" type="application/javascript"></script>
+</head>
+<body ng-app="Diller" ng-view>
+Loading Diller ...
+</body>
+</html>