new /count?uri=path and count.js

A separate (minified) JS to load only the comment count for each
`<a href="...#isso-thread">...</a>` link. If there are no comments,
return a 404, otherwise return the number JSON formatted.

To built `count.ks`, run `r.js -o build.count.js`.
pull/16/head
Martin Zimmermann 11 years ago
parent 1105e3e016
commit 45d4e18aef

@ -54,6 +54,7 @@ url_map = Map([
Rule('/', methods=['PUT', 'DELETE'], endpoint=views.comment.modify),
Rule('/new', methods=['POST'], endpoint=views.comment.create),
Rule('/like', methods=['POST'], endpoint=views.comment.like),
Rule('/count', methods=['GET'], endpoint=views.comment.count),
Rule('/admin/', endpoint=views.admin.index)
])

@ -73,6 +73,13 @@ class Abstract:
same ip address are ignored as well)."""
return
@abc.abstractmethod
def count(self, path=None, mode=1):
"""return count of comments for path (optional) and mode (defaults to
visible, not deleted or moderated comments)."""
return
class SQLite(Abstract):
"""A basic :class:`Abstract` implementation using SQLite3. All comments
share a single database. The tuple (id, path) acts as unique identifier
@ -213,6 +220,17 @@ class SQLite(Abstract):
return likes + 1
def count(self, path=None, mode=1):
if path is not None:
with sqlite3.connect(self.dbpath) as con:
return con.execute("SELECT COUNT(*) FROM comments WHERE path=?" \
+ " AND (? | mode) = ?", (path, mode, mode)).fetchone()
with sqlite3.connect(self.dbpath) as con:
return con.execute("SELECT COUNT(*) FROM comments WHERE" \
+ "(? | mode) = ?", (path, mode, mode)).fetchone()
def retrieve(self, path, mode=5):
with sqlite3.connect(self.dbpath) as con:
rv = con.execute("SELECT * FROM comments WHERE path=? AND (? | mode) = ?" \

@ -104,11 +104,22 @@ define(["lib/q"], function(Q) {
})
}
var count = function(uri) {
return curl("GET", endpoint + "/count?" + qs({uri: uri}), null)
.then(function (rv) {
if (rv.status == 200)
return JSON.parse(rv.body)
throw {status: rv.status, reason: rv.body};
})
}
return {
endpoint: endpoint,
create: create,
remove: remove,
fetchall: fetchall
fetchall: fetchall,
count: count
}
});

@ -0,0 +1,16 @@
define(["app/api", "lib/HTML"], function(api, HTML) {
return function() {
HTML.query("a").each(function(el, i, all) {
if (! el.href.match("#isso-thread$")) {
return;
};
var uri = el.href.match("^(.+)#isso-thread$")[1]
.replace(/^.*\/\/[^\/]+/, '');
console.log(uri)
api.count(uri).then(function(rv) {
el.textContent = rv + (rv > 1 ? " Kommentare" : " Kommentar");
})
});
}
});

@ -0,0 +1,7 @@
({
bseUrl: ".",
name: "lib/almond",
include: ['count'],
out: "count.min.js",
wrap: true
})

@ -0,0 +1,5 @@
require(["lib/ready", "app/count"], function(domready, count) {
domready(function() {
count();
})
});

@ -1,5 +1,6 @@
require(["lib/ready", "app/isso"], function(domready, isso) {
require(["lib/ready", "app/isso", "app/count"], function(domready, isso, count) {
domready(function() {
count();
isso.init();
})
});

@ -168,3 +168,14 @@ def approve(app, environ, request, path, id):
app.db.activate(path, id)
return Response(app.dumps(app.db.get(path, id)), 200,
content_type='application/json')
@requires(str, 'uri')
def count(app, environ, request, uri):
rv = app.db.count(uri, mode=1)[0]
if rv == 0:
abort(404)
return Response(json.dumps(rv), 200, content_type='application/json')

@ -201,3 +201,25 @@ class TestComments(unittest.TestCase):
assert rv.keys() == []
def testCounts(self):
assert self.get('/count?uri=%2Fpath%2F').status_code == 404
self.post('/new?uri=%2Fpath%2F', data=json.dumps({"text": "..."}))
rv = self.get('/count?uri=%2Fpath%2F')
assert rv.status_code == 200
assert json.loads(rv.data) == 1
for x in range(3):
self.post('/new?uri=%2Fpath%2F', data=json.dumps({"text": "..."}))
rv = self.get('/count?uri=%2Fpath%2F')
assert rv.status_code == 200
assert json.loads(rv.data) == 4
for x in range(4):
self.delete('/?uri=%%2Fpath%%2F&id=%i' % (x + 1))
rv = self.get('/count?uri=%2Fpath%2F')
assert rv.status_code == 404

Loading…
Cancel
Save