summaryrefslogtreecommitdiff
path: root/app
diff options
context:
space:
mode:
authorSean Fridman <fridman@mail.sfsu.edu>2015-07-09 16:58:02 -0400
committerSean Fridman <fridman@mail.sfsu.edu>2015-07-09 17:55:50 -0400
commit42fe17f3e52be163a506bf9a3953aa8adb5fd64f (patch)
treee4320eaf5ae38d18299fb4b5b046b8b28ed6401b /app
parent9be28b4322a629b8fe7c35e8cdc42eb413c6d84a (diff)
Implement groupBy queries + admin interface
Diffstat (limited to 'app')
-rw-r--r--app/index.js14
-rw-r--r--app/node_modules/okadminview/index.js42
-rw-r--r--app/node_modules/okquery/index.js43
-rw-r--r--app/node_modules/okview/index.js26
4 files changed, 82 insertions, 43 deletions
diff --git a/app/index.js b/app/index.js
index 1c77728..d514f10 100644
--- a/app/index.js
+++ b/app/index.js
@@ -60,6 +60,7 @@ function OKCMS(options) {
'/': { template: 'index' }
};
var serviceConfig = options.services || {};
+ var adminConfig = options.admin || {}
var templateProvider = this._templateProvider = new OKTemplate({
root: templateRoot,
@@ -84,7 +85,7 @@ function OKCMS(options) {
this._createViews(viewConfig, db, meta, resourceCache, templateProvider,
errorHandler);
var adminViews = this._adminViews =
- this._createAdminViews(adminPath, app, express, resourceConfig,
+ this._createAdminViews(adminConfig, adminPath, app, express, resourceConfig,
resourceCache, adminTemplateProvider, adminMeta,
errorHandler);
@@ -194,9 +195,8 @@ OKCMS.prototype._createViews = function(viewConfig, db,
}
};
-OKCMS.prototype._createAdminViews = function(path, app, express,
- resourceConfig, resourceCache, templateProvider, meta,
- errorHandler) {
+OKCMS.prototype._createAdminViews = function(adminConfig, path, app, express,
+ resourceConfig, resourceCache, templateProvider, meta, errorHandler) {
var views = {};
var withTrail = withTrailingSlash(path);
var withoutTrail = withoutTrailingSlash(path);
@@ -221,7 +221,8 @@ OKCMS.prototype._createAdminViews = function(path, app, express,
resourceCache: resourceCache,
templateProvider: templateProvider,
meta: meta,
- errorHandler: errorHandler
+ errorHandler: errorHandler,
+ dashboardConfig: adminConfig.dashboard || {}
});
return views;
};
@@ -243,7 +244,8 @@ OKCMS.prototype._createQueries = function(queryConfig, resourceCache) {
query: query,
as: config.as,
sortBy: config.sortBy,
- descending: config.descending
+ descending: config.descending,
+ groupBy: config.groupBy
});
});
};
diff --git a/app/node_modules/okadminview/index.js b/app/node_modules/okadminview/index.js
index f6a7cdb..924f5a5 100644
--- a/app/node_modules/okadminview/index.js
+++ b/app/node_modules/okadminview/index.js
@@ -40,6 +40,8 @@ function OKAdminView(options) {
if (!options.errorHandler)
throw new Error('No error handler provided to OKAdminView');
+ var dashboardConfig = options.dashboardConfig || {}
+ var dashboardResourceConfig = dashboardConfig.resources || {}
var app = options.app;
var express = options.express;
var meta = options.meta;
@@ -79,10 +81,12 @@ function OKAdminView(options) {
var id = resource.getID(staticData);
// Check to see if there's a more specific instance
resource = resourceCache.get(type, id) || resource;
+ var resourceOptions = dashboardResourceConfig[type] || {}
+ var groupBy = resourceOptions.groupBy
if (resource.bound) {
- return OKQuery({resource: resource});;
+ return OKQuery({resource: resource, groupBy: groupBy})
} else {
- return OKQuery({resource: resource, query: config.query})
+ return OKQuery({resource: resource, query: config.query, groupBy: groupBy})
}
});
@@ -123,7 +127,7 @@ function OKAdminView(options) {
}));
router.get('/', function readIndex(req, res, next) {
- fetchIndexTemplateData(meta, indexQueries).then(function(data) {
+ fetchIndexTemplateData(meta, indexQueries, dashboardConfig).then(function(data) {
view.renderIndex(req, res, assign(data, {
success: req.flash('success'),
errors: req.flash('errors')
@@ -316,7 +320,9 @@ OKAdminView.prototype.renderResourceNew = function(req, res, data) {
/**
* Annotate template data with schema info
*/
-function fetchIndexTemplateData(meta, queries) {
+function fetchIndexTemplateData(meta, queries, dashboardConfig) {
+ var resourceConfig = dashboardConfig.resources
+
return Q.promise(function(resolve, reject) {
Q.all(queries.map(function(query) {
return query.get();
@@ -327,27 +333,15 @@ function fetchIndexTemplateData(meta, queries) {
var resource = queries[i].resource;
// We want the raw object spec
var spec = resource.spec;
- var key = pluralize(resource.type);
- if (!cache[key]) {
- cache[key] = {
- type: resource.type,
- spec: spec,
- data: []
- };
- }
-
- if (result.length) {
- result.forEach(addData)
- } else {
- addData(result);
+ var dashConf = resourceConfig[resource.type] || {}
+ var groupBy = dashConf.groupBy
+ var key = pluralize(resource.type)
+ cache[key] = {
+ type: resource.type,
+ spec: spec,
+ data: result,
+ groupBy: groupBy
}
-
- function addData(data) {
- // Report id to template under standard name
- data.id = resource.getID(data);
- cache[key].data.push(data);
- }
-
return cache;
}, {});
diff --git a/app/node_modules/okquery/index.js b/app/node_modules/okquery/index.js
index 4051f95..09d867d 100644
--- a/app/node_modules/okquery/index.js
+++ b/app/node_modules/okquery/index.js
@@ -43,10 +43,17 @@ function OKQuery(options) {
enumerable: true
});
+ Object.defineProperty(this, 'groupBy', {
+ value: options.groupBy,
+ writable: false,
+ enumerable: true
+ })
+
this.get = createQuery(resource, query, {
default: options.default,
sortField: sortField,
- descending : descending
+ descending : descending,
+ groupBy: options.groupBy
});
}
@@ -66,6 +73,9 @@ function createQuery(resource, query, options) {
if (options.default) {
query = withDefault(query, options.default);
}
+ if (options.groupBy) {
+ query = withGrouping(query, options.groupBy)
+ }
return query;
}
@@ -124,6 +134,37 @@ function queryBound(resource) {
};
}
+/**
+ * Transform the query such that the results are grouped by the
+ * given field
+ */
+function withGrouping(queryFn, groupField) {
+ return function() {
+ return Q.Promise(function(resolve, reject) {
+ queryFn().then(function(data) {
+ data = data || []
+ if (typeof data.length === 'undefined') {
+ data = [data]
+ }
+ var result = {}
+ result[groupField] = data.reduce(reduceToGroups, {})
+ resolve(result)
+ }, reject)
+ })
+ }
+
+ function reduceToGroups(acc, data) {
+ var groupName = data[groupField]
+ if (groupName) {
+ if (!acc[groupName]) {
+ acc[groupName] = []
+ }
+ acc[groupName].push(data)
+ }
+ return acc
+ }
+}
+
function withDefault(queryFn, resultDefault) {
return function() {
return Q.Promise(function(resolve, reject) {
diff --git a/app/node_modules/okview/index.js b/app/node_modules/okview/index.js
index fba1c18..5f99d59 100644
--- a/app/node_modules/okview/index.js
+++ b/app/node_modules/okview/index.js
@@ -135,25 +135,28 @@ function fetchTemplateData(meta, queries, id) {
if (!result) {
return cache;
}
- var resource = queries[i].resource;
- var type = queries[i].as || queries[i].type;
+ var query = queries[i]
+ var resource = query.resource;
+ var type = query.as || query.type;
var manyResult = isarray(result);
- // Inform template of ID in generic field
- if (manyResult) {
- result = result.map(function(data) {
- return assign({}, data, {id: resource.getID(data)})
- });
- } else {
- result = assign({}, result, {id: resource.getID(result)});
- }
+ var groupBy = query.groupBy
// If we have a lot of results for a certain type,
// we pluralize the key and yield an array of results
- if (cache[type] || manyResult) {
+ if (cache[type] || manyResult || groupBy) {
var plural = pluralize(type);
delete cache[type];
cache[plural] = [];
+ // Pluralize grouped field
+ if (query.groupBy) {
+ result = Object.keys(result).reduce(function(acc, key) {
+ acc[pluralize(key)] = result[key]
+ return acc
+ }, {})
+ }
if (manyResult) {
cache[plural] = cache[plural].concat(result);
+ } else if (groupBy) {
+ cache[plural] = result
} else {
cache[plural].push(result);
}
@@ -162,7 +165,6 @@ function fetchTemplateData(meta, queries, id) {
}
return cache;
}, {meta: meta});
-
resolve(normalized);
}
}).fail(reject);