Date: Thu, 9 Jul 2015 16:58:02 -0400
Subject: Implement groupBy queries + admin interface
---
app/index.js | 14 ++++---
app/node_modules/okadminview/index.js | 42 +++++++++------------
app/node_modules/okquery/index.js | 43 ++++++++++++++++++++-
app/node_modules/okview/index.js | 26 +++++++------
themes/okadmin/public/js/app.js | 12 +++---
themes/okadmin/templates/index.liquid | 71 +++++++++++++++++++++++++----------
6 files changed, 140 insertions(+), 68 deletions(-)
(limited to 'themes/okadmin/public')
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);
diff --git a/themes/okadmin/public/js/app.js b/themes/okadmin/public/js/app.js
index 4be0afc..8a827ff 100644
--- a/themes/okadmin/public/js/app.js
+++ b/themes/okadmin/public/js/app.js
@@ -1,5 +1,5 @@
var OKAdmin = function(){
-
+
// initialize our multi-image uploader with an element and a template
$(".group.image-list").each(function(){
var parent = this
@@ -79,7 +79,7 @@ var OKAdmin = function(){
// make the region sortable with drag-and-drop
$(".media-list ol, .image-list ol").sortable()
$(".media-list ol, .image-list ol").disableSelection()
-
+
// populate a video field with info from our url parser
var last_url
$(".video .url").on("focus", function(){
@@ -201,7 +201,7 @@ var OKAdmin = function(){
})
})
})
-
+
// delete individual records
$("#delete_form").submit(function(e){
if (confirm("Are you sure you want to delete this record?")) {
@@ -213,9 +213,9 @@ var OKAdmin = function(){
})
// reorder items in categories
- $(".resource-category").on("click", ".edit-btn", function(e) {
+ $(".resource-category:not(.grouped)").on("click", ".edit-btn", function(e) {
e.preventDefault();
- var $parent = $(e.delegateTarget);
+ var $parent = $(e.delegateTarget)
var $editBtn = $parent.find(".edit-btn");
var $cancelBtn = $parent.find(".cancel-btn");
var $saveBtn = $parent.find(".save-btn");
@@ -245,7 +245,7 @@ var OKAdmin = function(){
});
// save new category order
- $(".resource-category").on("submit", "form", function(e) {
+ $(".resource-category.root").on("submit", "form", function(e) {
var $parent = $(e.delegateTarget);
$parent.find(".resource-input").each(function(index) {
var $input = $(this);
diff --git a/themes/okadmin/templates/index.liquid b/themes/okadmin/templates/index.liquid
index e9ad538..7af84b6 100644
--- a/themes/okadmin/templates/index.liquid
+++ b/themes/okadmin/templates/index.liquid
@@ -7,33 +7,66 @@
{% assign name = pair[0] %}
{% assign resource = pair[1] %}
-
--
cgit v1.2.3-70-g09d2
From 71b86094ae6f2b4c5618d7d51dda0ec007a6cc83 Mon Sep 17 00:00:00 2001
From: Sean Fridman
Date: Mon, 3 Aug 2015 14:45:17 -0400
Subject: Fix bug where resource indices got messed up on admin page
---
themes/okadmin/public/js/app.js | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
(limited to 'themes/okadmin/public')
diff --git a/themes/okadmin/public/js/app.js b/themes/okadmin/public/js/app.js
index 8a827ff..c24605b 100644
--- a/themes/okadmin/public/js/app.js
+++ b/themes/okadmin/public/js/app.js
@@ -247,10 +247,12 @@ var OKAdmin = function(){
// save new category order
$(".resource-category.root").on("submit", "form", function(e) {
var $parent = $(e.delegateTarget);
- $parent.find(".resource-input").each(function(index) {
+ var $resources = $parent.find(".resource-input")
+ var length = $resources.length
+ $resources.each(function(index) {
var $input = $(this);
var parsed = JSON.parse($input.val());
- parsed.__index = index;
+ parsed.__index = length - index;
$input.val(JSON.stringify(parsed));
})
});
--
cgit v1.2.3-70-g09d2
From 4b93310234f878add1fe3f6cc9df45f72b1c8f4f Mon Sep 17 00:00:00 2001
From: Sean Fridman
Date: Fri, 18 Dec 2015 18:34:50 +0100
Subject: OK... sort shit the right way homie
Pretty much reverts 71b86094ae6f
Not sure why that commit even exists
---
themes/okadmin/public/js/app.js | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
(limited to 'themes/okadmin/public')
diff --git a/themes/okadmin/public/js/app.js b/themes/okadmin/public/js/app.js
index c24605b..b313f22 100644
--- a/themes/okadmin/public/js/app.js
+++ b/themes/okadmin/public/js/app.js
@@ -248,11 +248,10 @@ var OKAdmin = function(){
$(".resource-category.root").on("submit", "form", function(e) {
var $parent = $(e.delegateTarget);
var $resources = $parent.find(".resource-input")
- var length = $resources.length
$resources.each(function(index) {
var $input = $(this);
var parsed = JSON.parse($input.val());
- parsed.__index = length - index;
+ parsed.__index = index;
$input.val(JSON.stringify(parsed));
})
});
--
cgit v1.2.3-70-g09d2
From 57026202f9ac0b98cc744734a04bcee362b789a3 Mon Sep 17 00:00:00 2001
From: Sean Fridman
Date: Sun, 20 Dec 2015 03:06:47 +0100
Subject: Date type always defaults to current day
---
package.json | 2 +-
themes/okadmin/public/js/app.js | 14 ++++++++++++++
2 files changed, 15 insertions(+), 1 deletion(-)
(limited to 'themes/okadmin/public')
diff --git a/package.json b/package.json
index b7f1105..192685c 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "okcms",
- "version": "0.1.16",
+ "version": "0.1.18",
"description": "great",
"main": "app/index.js",
"scripts": {
diff --git a/themes/okadmin/public/js/app.js b/themes/okadmin/public/js/app.js
index b313f22..edf9980 100644
--- a/themes/okadmin/public/js/app.js
+++ b/themes/okadmin/public/js/app.js
@@ -20,6 +20,20 @@ var OKAdmin = function(){
}
})
+ // Add default date
+ $('.date input').each(function(i, el){
+ var value = el.getAttribute('value')
+ if (!value) {
+ el.setAttribute('value', toDateInputValue(new Date))
+ }
+
+ function toDateInputValue (date) {
+ var local = new Date(date);
+ local.setMinutes(date.getMinutes() - date.getTimezoneOffset());
+ return local.toJSON().slice(0,10);
+ }
+ })
+
// initialize our multimedia uploader with an element and a template
$(".group.media-list").each(function(){
var parent = this
--
cgit v1.2.3-70-g09d2
From 8898bbe48285c7f9f11760ef420cca43d683d5e0 Mon Sep 17 00:00:00 2001
From: Jules Laplace
Date: Mon, 28 Mar 2016 13:59:50 -0400
Subject: modify links field to specify text and uri
---
app/index.js | 1 +
app/node_modules/okdb/index.js | 2 +-
app/node_modules/okschema/index.js | 17 +++++++-
examples/db.json | 9 +++-
examples/index.js | 5 ++-
package.json | 2 +-
themes/okadmin/public/css/main.css | 8 ++++
themes/okadmin/public/js/app.js | 34 ++++++---------
themes/okadmin/templates/partials/inputs.liquid | 56 +++++++++++++++++++------
9 files changed, 93 insertions(+), 41 deletions(-)
(limited to 'themes/okadmin/public')
diff --git a/app/index.js b/app/index.js
index 6a1c74f..06b1591 100644
--- a/app/index.js
+++ b/app/index.js
@@ -28,6 +28,7 @@ function OKCMS(options) {
var app = express();
app.enable('strict routing');
+ app.disable('x-powered-by');
var root = this._root = options.root || 'public';
var adminConfig = options.admin || {};
diff --git a/app/node_modules/okdb/index.js b/app/node_modules/okdb/index.js
index 4820c8c..ad8d9a7 100644
--- a/app/node_modules/okdb/index.js
+++ b/app/node_modules/okdb/index.js
@@ -97,7 +97,7 @@ FSDB.prototype.update = function(collection, id, data) {
}
var result = chain.assign(cloneDeep(data)).value();
- if (result ) {
+ if (result) {
return resolve(cloneDeep(result));
} else {
return resolve(null, new Error('Problem updating document'));
diff --git a/app/node_modules/okschema/index.js b/app/node_modules/okschema/index.js
index 330ad6b..82aa13f 100644
--- a/app/node_modules/okschema/index.js
+++ b/app/node_modules/okschema/index.js
@@ -63,8 +63,21 @@ var types = {
assertValid: function(spec, value) {}
},
'tag-list': {
- parent: 'string',
- assertValid: function(spec, value) {}
+ parent: [{
+ uri: { type: 'string' },
+ text: { type: 'string' }
+ }],
+ assertValid: function(spec, value) {
+ var message;
+ var actual;
+ if (!value || !value.length) {
+ throw [{
+ message: 'Not an array',
+ expected: JSON.stringify(this.parent),
+ actual: value
+ }];
+ }
+ }
},
'date': {
parent: 'string',
diff --git a/examples/db.json b/examples/db.json
index 20d4510..4319237 100644
--- a/examples/db.json
+++ b/examples/db.json
@@ -99,7 +99,14 @@
"title": "About Us",
"body": "Just a small bakery",
"id": "about",
- "__index": 1
+ "__index": "1",
+ "links": [
+ {
+ "text": "asdf2",
+ "uri": "asdf"
+ }
+ ],
+ "dateCreated": ""
},
{
"title": "ok...",
diff --git a/examples/index.js b/examples/index.js
index 3e9f509..bf51dfc 100644
--- a/examples/index.js
+++ b/examples/index.js
@@ -10,7 +10,8 @@ var app = okcms.createApp({
page: {
id: {type: 'string'},
title: {type: 'string'},
- body: {type: 'text'}
+ body: {type: 'text'},
+ links: {type: 'link-list'},
},
bread: {
type: {type: 'string', id: true},
@@ -19,7 +20,7 @@ var app = okcms.createApp({
color: {type: 'enum', options: ["red","blue","green"]},
video: {type: 'video'},
images: {type: 'captioned-image-list'}
- }
+ },
},
resources: [
diff --git a/package.json b/package.json
index 192685c..faf3cc9 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "okcms",
- "version": "0.1.18",
+ "version": "0.1.19",
"description": "great",
"main": "app/index.js",
"scripts": {
diff --git a/themes/okadmin/public/css/main.css b/themes/okadmin/public/css/main.css
index a5fbdeb..9289fdf 100644
--- a/themes/okadmin/public/css/main.css
+++ b/themes/okadmin/public/css/main.css
@@ -305,6 +305,14 @@ button, input[type=submit] {
.main.resource form .video-element input[type=text] {
width: 15em;
}
+.main.resource form .group input[type=text].link-input,
+.main.resource form .group input[type=text].link-input-new {
+ width: 13.05em;
+ padding: 0 0 0 0.5em;
+}
+.main.resource form .links li {
+ height: auto;
+}
.main .link-list .add-link-btn,
.main .link-list .remove-link-btn {
margin: 0;
diff --git a/themes/okadmin/public/js/app.js b/themes/okadmin/public/js/app.js
index edf9980..17b35d0 100644
--- a/themes/okadmin/public/js/app.js
+++ b/themes/okadmin/public/js/app.js
@@ -120,35 +120,25 @@ var OKAdmin = function(){
e.stopPropagation()
var $delegate = $(e.delegateTarget)
var $list = $delegate.find('.links')
- var length = $list.find('input').length
- var name = $delegate.parent('.property').data('name')
- var $new = $delegate.find('.link-input-new')
- var input = document.createElement('input')
- var delBtn = document.createElement('button')
- var inputName = name + '[' + length + ']'
- $(input).attr({
- name: inputName,
- type: 'text',
- value: $new.val()
- })
- $list.append(input)
- $(delBtn).addClass('remove-link-btn')
- $(delBtn).data('for', inputName)
- delBtn.innerHTML = '-'
- $list.append(delBtn)
- $new.val('')
+ var $linkText = $delegate.find(".link-input-new.link-text")
+ var $linkURI = $delegate.find(".link-input-new.link-uri")
+
+ var template = $delegate.find(".link-template").html()
+ var $el = $(template)
+ $el.find(".link-text").val( $linkText.val() )
+ $el.find(".link-uri").val( $linkURI.val() )
+ $list.append($el)
+ console.log($list, template)
+ $linkText.val("")
+ $linkURI.val("")
})
// Remove a link from the list
$('.link-list').on('click', '.remove-link-btn', function(e) {
e.preventDefault()
e.stopPropagation()
- var $delegate = $(e.delegateTarget)
var $target = $(e.target)
- var inputName = $target.data('for')
- var $input = $delegate.find('[name="' + inputName + '"]')
- $input.remove()
- $target.remove()
+ $target.closest("li").remove()
})
// fix post indexing in list-driven inputs
diff --git a/themes/okadmin/templates/partials/inputs.liquid b/themes/okadmin/templates/partials/inputs.liquid
index c6efc68..55d5fb8 100644
--- a/themes/okadmin/templates/partials/inputs.liquid
+++ b/themes/okadmin/templates/partials/inputs.liquid
@@ -79,26 +79,58 @@
value="{{spec.value}}"
placeholder="Enter a comma separated list of tags.">
- {% elsif type == 'link-list' %}
+ {% elsif type == 'link-list' %}
{% elsif type == 'media-list' %}
--
cgit v1.2.3-70-g09d2
From 49fe25c8e884c14ab3258d22240a62f0b57da490 Mon Sep 17 00:00:00 2001
From: Jules Laplace