Implement layout and device list page

This commit is contained in:
Zaid Abdulla committed 2018-12-26 00:20:45 -08:00
1 parent f33717acb0
commit 1c9061ab5a
19 files changed
+1151 -30

No files matched your search

+51 -4
View File
@@ -6,6 +6,7 @@ const url = require("url");
const querystring = require("querystring");
const config = require("./config");
const device = require("./device");
const commaAscii = ",".charCodeAt(0);
const newLineAscii = "\n".charCodeAt(0);
@@ -19,6 +20,7 @@ function filtersToQuery(filters) {
for (let [k, v] of Object.entries(filter)) {
let [param, op] = k.split(/([^a-zA-Z0-9\-_.].*)/, 2);
if (!op || op === "=") q[param] = v;
else if (op === ">") q[param] = { $gt: v };
else throw new Error(`Operator "${op}" not recognized`);
}
queries.push(q);
@@ -28,22 +30,63 @@ function filtersToQuery(filters) {
else return { $or: queries };
}
function count(resource, filters, limit) {
return new Promise((resolve, reject) => {
let qs = {};
if (filters) {
let q = filtersToQuery(filters);
if (resource === "devices") q = device.transposeQuery(q);
qs.query = JSON.stringify(q);
}
if (limit) qs.limit = limit;
let options = url.parse(
`${config.GENIEACS_NBI}${resource}?${querystring.stringify(qs)}`
);
options.method = "HEAD";
let _http = options.protocol === "https:" ? https : http;
_http
.request(options, res => {
if (res.statusCode !== 200) {
reject(new Error(`Unexpected status code ${res.statusCode}`));
res.resume();
return;
}
resolve(+res.headers["total"]);
})
.end();
});
}
function query(resource, filters, limit, callback) {
return new Promise((resolve, reject) => {
let ret;
if (!callback) ret = [];
let q = {};
if (filters) q.query = JSON.stringify(filtersToQuery(filters));
let qs = {};
if (filters) {
let q = filtersToQuery(filters);
if (resource === "devices") q = device.transposeQuery(q);
qs.query = JSON.stringify(q);
}
if (limit) q.limit = limit;
if (limit) qs.limit = limit;
let options = url.parse(
`${config.GENIEACS_NBI}${resource}?${querystring.stringify(q)}`
`${config.GENIEACS_NBI}${resource}?${querystring.stringify(qs)}`
);
let _http = options.protocol === "https:" ? https : http;
_http.get(options, res => {
if (res.statusCode !== 200) {
reject(new Error(`Unexpected status code ${res.statusCode}`));
res.resume();
return;
}
let chunks = [];
let bytes = 0;
res.on("data", chunk => {
@@ -69,6 +112,7 @@ function query(resource, filters, limit, callback) {
if (buf.length > 1) {
let obj = JSON.parse(buf);
if (resource === "devices") obj = device.transpose(obj);
if (ret) ret.push(obj);
else callback(obj);
}
@@ -89,6 +133,8 @@ function query(resource, filters, limit, callback) {
}
if (buf.length > 1) {
let obj = JSON.parse(buf);
if (resource === "devices") obj = device.transpose(obj);
if (ret) ret.push(obj);
else callback(obj);
}
@@ -104,3 +150,4 @@ function query(resource, filters, limit, callback) {
}
exports.query = query;
exports.count = count;
+15 -15
View File
@@ -16,35 +16,35 @@ const resources = {
for (let [resource, update] of Object.entries(resources)) {
router.head(`/${resource}`, async ctx => {
let filters, limit;
if (ctx.request.query.query)
if (Array.isArray(ctx.request.query.query))
filters = ctx.request.query.query.map(q => JSON.parse(q));
let filter, limit;
if (ctx.request.query.filter)
if (Array.isArray(ctx.request.query.filter))
filter = ctx.request.query.query.map(q => JSON.parse(q));
else {
filters = JSON.parse(ctx.request.query.query);
if (!Array.isArray(filters)) filters = [filters];
filter = JSON.parse(ctx.request.query.filter);
if (!Array.isArray(filter)) filter = [filter];
}
if (ctx.request.query.limit) limit = +ctx.request.query.limit;
let res = await apiFunctions.query(resource, filters, limit);
ctx.set("X-Total-Count", res.length);
let count = await apiFunctions.count(resource, filter, limit);
ctx.set("X-Total-Count", count);
ctx.body = "";
});
router.get(`/${resource}`, async ctx => {
let filters, limit;
if (ctx.request.query.query)
if (Array.isArray(ctx.request.query.query))
filters = ctx.request.query.query.map(q => JSON.parse(q));
let filter, limit;
if (ctx.request.query.filter)
if (Array.isArray(ctx.request.query.filter))
filter = ctx.request.query.query.map(q => JSON.parse(q));
else {
filters = JSON.parse(ctx.request.query.query);
if (!Array.isArray(filters)) filters = [filters];
filter = JSON.parse(ctx.request.query.filter);
if (!Array.isArray(filter)) filter = [filter];
}
if (ctx.request.query.limit) limit = +ctx.request.query.limit;
ctx.body = await apiFunctions.query(resource, filters, limit);
ctx.body = await apiFunctions.query(resource, filter, limit);
});
router.head(`/${resource}/:id`, async (ctx, next) => {
+152
View File
@@ -0,0 +1,152 @@
"use strict";
function recursive(input, root, output, timestamp) {
for (let [name, tree] of Object.entries(input)) {
if (root.length === 0)
if (name === "_lastInform") {
output["Events.Inform"] = {
value: [timestamp, "xsd:dateTime"],
valueTimestamp: timestamp,
writable: false,
writableTimestamp: timestamp,
object: false,
objectTimestamp: timestamp
};
} else if (name === "_registered") {
output["Events.Registered"] = {
value: [timestamp, "xsd:dateTime"],
valueTimestamp: timestamp,
writable: false,
writableTimestamp: timestamp,
object: false,
objectTimestamp: timestamp
};
} else if (name === "_lastBoot") {
output["Events.1_BOOT"] = {
value: [timestamp, "xsd:dateTime"],
valueTimestamp: timestamp,
writable: false,
writableTimestamp: timestamp,
object: false,
objectTimestamp: timestamp
};
} else if (name === "_lastBootstrap") {
output["Events.0_BOOTSTRAP"] = {
value: [timestamp, "xsd:dateTime"],
valueTimestamp: timestamp,
writable: false,
writableTimestamp: timestamp,
object: false,
objectTimestamp: timestamp
};
} else if (name === "_id") {
output["DeviceID.ID"] = {
value: [tree, "xsd:string"],
valueTimestamp: timestamp,
writable: false,
writableTimestamp: timestamp,
object: false,
objectTimestamp: timestamp
};
} else if (name === "_deviceId") {
output["DeviceID.Manufacturer"] = {
value: [tree["_Manufacturer"], "xsd:string"],
valueTimestamp: timestamp,
writable: false,
writableTimestamp: timestamp,
object: false,
objectTimestamp: timestamp
};
output["DeviceID.OUI"] = {
value: [tree["_OUI"], "xsd:string"],
valueTimestamp: timestamp,
writable: false,
writableTimestamp: timestamp,
object: false,
objectTimestamp: timestamp
};
output["DeviceID.ProductClass"] = {
value: [tree["_ProductClass"], "xsd:string"],
valueTimestamp: timestamp,
writable: false,
writableTimestamp: timestamp,
object: false,
objectTimestamp: timestamp
};
output["DeviceID.SerialNumber"] = {
value: [tree["_SerialNumber"], "xsd:string"],
valueTimestamp: timestamp,
writable: false,
writableTimestamp: timestamp,
object: false,
objectTimestamp: timestamp
};
} else if (name === "_tags") {
output["Tags"] = {
writable: true,
writableTimestamp: timestamp,
object: true,
objectTimestamp: timestamp
};
for (let t of tree)
output[`Tags.${t}`] = {
value: [true, "xsd:boolean"],
valueTimestamp: timestamp,
writable: false,
writableTimestamp: timestamp,
object: false,
objectTimestamp: timestamp
};
}
if (name.startsWith("_")) continue;
let childrenTimestamp = timestamp;
if (root.length === 0) childrenTimestamp = input["_timestamp"] || 1;
else if (input["_timestamp"] > timestamp)
childrenTimestamp = input["_timestamp"];
const attrs = {};
if (tree["_value"]) {
attrs["value"] = [tree["_value"], tree["_type"]];
attrs["valueTimestamp"] = childrenTimestamp;
attrs["object"] = false;
attrs["objectTimestamp"] = childrenTimestamp;
} else if (tree["_object"]) {
attrs["object"] = tree["_object"];
attrs["objectTimestamp"] = childrenTimestamp;
}
if (tree["_writable"]) {
attrs["writable"] = tree["_writable"];
attrs["writableTimestamp"] = childrenTimestamp;
}
let r = root.concat(name);
output[r.join(".")] = attrs;
if (attrs["object"]) recursive(tree, r, output, childrenTimestamp);
}
}
function transpose(device) {
const newDevice = {};
const timestamp = new Date(device["_lastInform"] || 1).getTime();
recursive(device, [], newDevice, timestamp);
return newDevice;
}
function transposeQuery(query) {
const newQuery = {};
for (let [key, val] of Object.entries(query))
if (key.startsWith("$")) newQuery[key] = transposeQuery(val);
else if (key === "DeviceID.ID") newQuery["_id"] = val;
return newQuery;
}
exports.transpose = transpose;
exports.transposeQuery = transposeQuery;