From 0a93c866ff7baa42de72f03cd827e0607b888b9e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Latinier?= Date: Sun, 5 Jun 2016 01:10:08 +0200 Subject: [PATCH 01/10] Add a basic admin interface (Fix issue #10) Add a basic admin interface (Fix issue #10) wip again still wip fix login page --- isso/__init__.py | 1 + isso/css/admin.css | 115 ++++++++++++++++++++++++++++ isso/db/comments.py | 59 ++++++++++++++- isso/img/isso.svg | 2 + isso/templates/admin.html | 154 ++++++++++++++++++++++++++++++++++++++ isso/templates/login.html | 30 ++++++++ isso/utils/__init__.py | 18 ++++- isso/views/comments.py | 47 +++++++++++- setup.py | 2 +- share/isso-dev.conf | 1 + share/isso.conf | 5 +- 11 files changed, 427 insertions(+), 7 deletions(-) create mode 100644 isso/css/admin.css create mode 100644 isso/img/isso.svg create mode 100644 isso/templates/admin.html create mode 100644 isso/templates/login.html diff --git a/isso/__init__.py b/isso/__init__.py index 7795c4f..f842882 100644 --- a/isso/__init__.py +++ b/isso/__init__.py @@ -186,6 +186,7 @@ def make_app(conf=None, threading=True, multiprocessing=False, uwsgi=False): wrapper.append(partial(SharedDataMiddleware, exports={ '/js': join(dirname(__file__), 'js/'), '/css': join(dirname(__file__), 'css/'), + '/img': join(dirname(__file__), 'img/'), '/demo': join(dirname(__file__), 'demo/') })) diff --git a/isso/css/admin.css b/isso/css/admin.css new file mode 100644 index 0000000..6f747b9 --- /dev/null +++ b/isso/css/admin.css @@ -0,0 +1,115 @@ +* { + box-sizing: border-box; + margin: 0; + padding: 0; +} +h1, h2, h3, h4, h5, h6 { + font-style: normal; + font-weight: normal; +} +input { + text-align: center; +} +.header::before, .header::after { + content: " "; + display: table; +} +.header::after { + clear: both; +} +.header::before, .header::after { + content: " "; + display: table; +} +.header { + margin-left: auto; + margin-right: auto; + max-width: 68em; + padding-bottom: 1em; + padding-top: 1em; +} +.header header { + display: block; + float: left; + font-weight: normal; + margin-right: 16.0363%; + width: 41.9818%; +} +.header header .logo { + float: left; + max-height: 60px; + padding-right: 12px; +} +.header header h1 { + font-size: 1.55em; + margin-bottom: 0.3em; +} +.header header h2 { + font-size: 1.05em; +} +.header a, .header a:visited { + color: #4d4c4c; + text-decoration: none; +} +.outer { + background-color: #eeeeee; + box-shadow: 0 0 0.5em #c0c0c0 inset; +} +.outer .filters::before, .outer .filters::after { + content: " "; + display: table; +} +.outer .filters::after { + clear: both; +} +.outer .filters::before, .outer .filters::after { + content: " "; + display: table; +} +.outer .filters { + margin-left: auto; + margin-right: auto; + max-width: 68em; + padding: 1em; +} + +a { + text-decoration: none; + color: #4d4c4c; +} +.label { + background-color: #ddd; + border: 1px solid #ccc; + border-radius: 2px; + box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1); + cursor: pointer; + line-height: 1.4em; + outline: 0 none; + padding: calc(0.6em - 1px); +} +.active { + box-shadow: 2px 2px 2px rgba(0, 0, 0, 0.6) inset; +} +.label-valid { + background-color: #cfc; + border-color: #cfc; +} +.label-pending { + background-color: #ffc; + border-color: #ffc; +} +.mode { + float: left; +} +.pagination { + float: right; +} +.note .label { + margin: 9px; + padding: 3px; +} +#login { + margin-top: 40px; + text-align: center; + width: 100%; +} diff --git a/isso/db/comments.py b/isso/db/comments.py index 496a4e5..69790ac 100644 --- a/isso/db/comments.py +++ b/isso/db/comments.py @@ -19,8 +19,11 @@ class Comments: The tuple (tid, id) is unique and thus primary key. """ - fields = ['tid', 'id', 'parent', 'created', 'modified', 'mode', 'remote_addr', - 'text', 'author', 'email', 'website', 'likes', 'dislikes', 'voters'] + fields = ['tid', 'id', 'parent', 'created', 'modified', + 'mode', # status of the comment 1 = valid, 2 = pending, + # 4 = soft-deleted (cannot hard delete because of replies) + 'remote_addr', 'text', 'author', 'email', 'website', + 'likes', 'dislikes', 'voters'] def __init__(self, db): @@ -97,6 +100,58 @@ class Comments: return None + def count_modes(self): + """ + Return comment mode counts for admin + """ + comment_count = self.db.execute( + 'SELECT mode, COUNT(comments.id) FROM comments ' + 'GROUP BY comments.mode').fetchall() + return dict(comment_count) + + def fetchall(self, mode=5, after=0, parent='any', order_by='id', + limit=100, page=0): + """ + Return comments for admin with :param:`mode`. + """ + fields_comments = ['tid', 'id', 'parent', 'created', 'modified', + 'mode', 'remote_addr', 'text', 'author', + 'email', 'website', 'likes', 'dislikes'] + fields_threads = ['uri', 'title'] + sql_comments_fields = ', '.join(['comments.' + f + for f in fields_comments]) + sql_threads_fields = ', '.join(['threads.' + f + for f in fields_threads]) + sql = ['SELECT ' + sql_comments_fields + ', ' + \ + sql_threads_fields + ' ' + 'FROM comments INNER JOIN threads ' + 'ON comments.tid=threads.id ' + 'WHERE comments.mode = ? '] + sql_args = [mode] + + if parent != 'any': + if parent is None: + sql.append('AND comments.parent IS NULL') + else: + sql.append('AND comments.parent=?') + sql_args.append(parent) + + # custom sanitization + if order_by not in ['id', 'created', 'modified', 'likes', 'dislikes']: + order_by = 'id' + sql.append('ORDER BY ') + sql.append('comments.' + order_by) + sql.append(' DESC') + + if limit: + sql.append('LIMIT ?,?') + sql_args.append(page * limit) + sql_args.append(limit) + + rv = self.db.execute(sql, sql_args).fetchall() + for item in rv: + yield dict(zip(fields_comments + fields_threads, item)) + def fetch(self, uri, mode=5, after=0, parent='any', order_by='id', limit=None): """ Return comments for :param:`uri` with :param:`mode`. diff --git a/isso/img/isso.svg b/isso/img/isso.svg new file mode 100644 index 0000000..1aba2dd --- /dev/null +++ b/isso/img/isso.svg @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/isso/templates/admin.html b/isso/templates/admin.html new file mode 100644 index 0000000..f3d9a53 --- /dev/null +++ b/isso/templates/admin.html @@ -0,0 +1,154 @@ + + + Isso admin + + + + + +
+ +
+
+ + +
+
+
+ {% for comment in comments %} +
+ {% if conf.avatar %} +
+ svg(data-hash='#{{comment.hash}}') +
+ {% endif %} +
+
+ {% if comment.author %} + {{comment.author}} + {% else %} + Anonymous + {% endif %} + {% if comment.website %} + ({{comment.website}}) + {% endif %} + + + + {% if comment.mode == 1 %} + Valid + {% elif comment.mode == 2 %} + Pending + {% elif comment.mode == 4 %} + Staled + {% endif %} + +
+
+ {% if comment.mode == 4 %} + HIDDEN. Original text:
+ {% endif %} + {{comment.text}} +
+ +
+
+ {% endfor %} +
+
+ + diff --git a/isso/templates/login.html b/isso/templates/login.html new file mode 100644 index 0000000..a9aa888 --- /dev/null +++ b/isso/templates/login.html @@ -0,0 +1,30 @@ + + + Isso admin + + + + +
+ +
+
+ Administration secured by password: +
+ +
+
+
+
+ + diff --git a/isso/utils/__init__.py b/isso/utils/__init__.py index a7cafd5..7536041 100644 --- a/isso/utils/__init__.py +++ b/isso/utils/__init__.py @@ -5,9 +5,12 @@ from __future__ import division, unicode_literals import pkg_resources werkzeug = pkg_resources.get_distribution("werkzeug") -import json import hashlib +import json +import os +from datetime import datetime +from jinja2 import Environment, FileSystemLoader from werkzeug.wrappers import Response from werkzeug.exceptions import BadRequest @@ -109,6 +112,19 @@ class JSONRequest(Request): raise BadRequest('Unable to read JSON request') +def render_template(template_name, **context): + template_path = os.path.join(os.path.dirname(__file__), + '..', 'templates') + jinja_env = Environment(loader=FileSystemLoader(template_path), + autoescape=True) + def datetimeformat(value): + return datetime.fromtimestamp(value).strftime('%H:%M / %d-%m-%Y') + + jinja_env.filters['datetimeformat'] = datetimeformat + t = jinja_env.get_template(template_name) + return Response(t.render(context), mimetype='text/html') + + class JSONResponse(Response): def __init__(self, obj, *args, **kwargs): diff --git a/isso/views/comments.py b/isso/views/comments.py index d328305..68c228f 100644 --- a/isso/views/comments.py +++ b/isso/views/comments.py @@ -7,6 +7,7 @@ import cgi import time import functools +from datetime import datetime, timedelta from itsdangerous import SignatureExpired, BadSignature from werkzeug.http import dump_cookie @@ -15,11 +16,13 @@ from werkzeug.utils import redirect from werkzeug.routing import Rule from werkzeug.wrappers import Response from werkzeug.exceptions import BadRequest, Forbidden, NotFound +from werkzeug.contrib.securecookie import SecureCookie from isso.compat import text_type as str from isso import utils, local -from isso.utils import http, parse, JSONResponse as JSON +from isso.utils import (http, parse, JSONResponse as JSON, + render_template) from isso.views import requires from isso.utils.hash import sha1 @@ -90,7 +93,9 @@ class API(object): ('like', ('POST', '/id//like')), ('dislike', ('POST', '/id//dislike')), ('demo', ('GET', '/demo')), - ('preview', ('POST', '/preview')) + ('preview', ('POST', '/preview')), + ('login', ('POST', '/login')), + ('admin', ('GET', '/admin')) ] def __init__(self, isso, hasher): @@ -490,3 +495,41 @@ class API(object): def demo(self, env, req): return redirect(get_current_url(env) + '/index.html') + + def login(self, env, req): + data = req.form + password = self.isso.conf.get("general", "admin_password") + if data['password'] and data['password'] == password: + response = redirect(get_current_url(env, host_only=True) + '/admin') + cookie = functools.partial(dump_cookie, + value=self.isso.sign({"logged": True}), + expires=datetime.now() + timedelta(1)) + response.headers.add("Set-Cookie", cookie("admin-session")) + response.headers.add("X-Set-Cookie", cookie("isso-admin-session")) + return response + else: + return render_template('login.html') + + def admin(self, env, req): + try: + data = self.isso.unsign(req.cookies.get('admin-session', ''), + max_age=60 * 60 * 24) + except BadSignature: + return render_template('login.html') + if not data or not data['logged']: + return render_template('login.html') + page_size = 100 + page = req.args.get('page', 0) + mode = req.args.get('mode', 2) + comments = self.comments.fetchall(mode=mode, page=page, + limit=page_size) + comments_enriched = [] + for comment in list(comments): + comment['hash'] = self.isso.sign(comment['id']) + comments_enriched.append(comment) + comment_mode_count = self.comments.count_modes() + max_page = int(sum(comment_mode_count.values()) / 100) + return render_template('admin.html', comments=comments_enriched, + page=int(page), mode=int(mode), + conf=self.conf, max_page=max_page, + counts=comment_mode_count) diff --git a/setup.py b/setup.py index e54c110..b2c7482 100644 --- a/setup.py +++ b/setup.py @@ -5,7 +5,7 @@ import sys from setuptools import setup, find_packages -requires = ['itsdangerous', 'misaka>=1.0,<2.0', 'html5lib==0.9999999'] +requires = ['itsdangerous', 'misaka>=1.0,<2.0', 'html5lib==0.9999999', 'Jinja2'] if (3, 0) <= sys.version_info < (3, 3): raise SystemExit("Python 3.0, 3.1 and 3.2 are not supported") diff --git a/share/isso-dev.conf b/share/isso-dev.conf index ce87ab3..970c1b0 100644 --- a/share/isso-dev.conf +++ b/share/isso-dev.conf @@ -10,6 +10,7 @@ host = http://isso-dev.local/ max-age = 15m notify = stdout log-file = /var/log/isso.log +admin_password = strong_default_password_for_isso_admin [moderation] enabled = false diff --git a/share/isso.conf b/share/isso.conf index 7c275ac..5dcf987 100644 --- a/share/isso.conf +++ b/share/isso.conf @@ -43,9 +43,12 @@ max-age = 15m # moderated) and deletion links. notify = stdout -# Log console messages to file instead of standard out. +# Log console messages to file instead of standard output. log-file = +# Admin access password +admin_password = please_choose_a_strong_password + [moderation] # enable comment moderation queue. This option only affects new comments. From 7a79746f73ee928ea80e28a4657e8c5a6762920d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Latinier?= Date: Sat, 16 Jul 2016 00:05:33 +0200 Subject: [PATCH 02/10] add: show author email --- isso/templates/admin.html | 3 +++ 1 file changed, 3 insertions(+) diff --git a/isso/templates/admin.html b/isso/templates/admin.html index f3d9a53..c32ff1e 100644 --- a/isso/templates/admin.html +++ b/isso/templates/admin.html @@ -108,6 +108,9 @@ function delete_com(com_id, hash) { {% else %} Anonymous {% endif %} + {% if comment.email %} + + {% endif %} {% if comment.website %} ({{comment.website}}) {% endif %} From 1516f56cbda9616cba2f6b8116c990574247d688 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Latinier?= Date: Sat, 16 Jul 2016 00:09:23 +0200 Subject: [PATCH 03/10] fix: cursor pointer on links delete/validate --- isso/css/admin.css | 3 +++ 1 file changed, 3 insertions(+) diff --git a/isso/css/admin.css b/isso/css/admin.css index 6f747b9..d6a8f74 100644 --- a/isso/css/admin.css +++ b/isso/css/admin.css @@ -113,3 +113,6 @@ a { text-align: center; width: 100%; } +.isso-comment-footer a { + cursor: pointer; +} From 0b6a0e4d5fc17be9280c80eef5f38c68c809ea5f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Latinier?= Date: Sat, 16 Jul 2016 00:53:52 +0200 Subject: [PATCH 04/10] add: group by thread --- isso/css/admin.css | 7 +++++++ isso/db/comments.py | 4 ++-- isso/templates/admin.html | 13 +++++++++++++ isso/views/comments.py | 7 +++++-- 4 files changed, 27 insertions(+), 4 deletions(-) diff --git a/isso/css/admin.css b/isso/css/admin.css index d6a8f74..5a434fc 100644 --- a/isso/css/admin.css +++ b/isso/css/admin.css @@ -116,3 +116,10 @@ a { .isso-comment-footer a { cursor: pointer; } +.thread-title { + margin-left: 3em; +} +.group { + float: left; + margin-left: 2em; +} diff --git a/isso/db/comments.py b/isso/db/comments.py index 69790ac..62cfad2 100644 --- a/isso/db/comments.py +++ b/isso/db/comments.py @@ -137,10 +137,10 @@ class Comments: sql_args.append(parent) # custom sanitization - if order_by not in ['id', 'created', 'modified', 'likes', 'dislikes']: + if order_by not in ['id', 'created', 'modified', 'likes', 'dislikes', 'tid']: order_by = 'id' sql.append('ORDER BY ') - sql.append('comments.' + order_by) + sql.append('comments.' + order_by + ", comments.created") sql.append(' DESC') if limit: diff --git a/isso/templates/admin.html b/isso/templates/admin.html index c32ff1e..9d10816 100644 --- a/isso/templates/admin.html +++ b/isso/templates/admin.html @@ -77,6 +77,9 @@ function delete_com(com_id, hash) { +
+ Group by thread: +
+ {% set thread_id = "no_id" %} {% for comment in comments %} + {% if order_by == "tid" %} + {% if thread_id != comment.tid %} + {% set thread_id = comment.tid %} +

{{comment.title}}

+ {% endif %} + {% endif %}
{% if conf.avatar %}
@@ -103,6 +113,9 @@ function delete_com(com_id, hash) { {% endif %}
+ {% if order_by != "tid" %} + Thread: {{comment.title}}
+ {% endif %} {% if comment.author %} {{comment.author}} {% else %} diff --git a/isso/views/comments.py b/isso/views/comments.py index 68c228f..df1eebe 100644 --- a/isso/views/comments.py +++ b/isso/views/comments.py @@ -520,9 +520,11 @@ class API(object): return render_template('login.html') page_size = 100 page = req.args.get('page', 0) + order_by = req.args.get('order_by', "id") mode = req.args.get('mode', 2) comments = self.comments.fetchall(mode=mode, page=page, - limit=page_size) + limit=page_size, + order_by=order_by) comments_enriched = [] for comment in list(comments): comment['hash'] = self.isso.sign(comment['id']) @@ -532,4 +534,5 @@ class API(object): return render_template('admin.html', comments=comments_enriched, page=int(page), mode=int(mode), conf=self.conf, max_page=max_page, - counts=comment_mode_count) + counts=comment_mode_count, + order_by=order_by) From 3212bf762fc8fa152fd3323b0afaed103f68d728 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Latinier?= Date: Thu, 27 Oct 2016 23:18:37 +0200 Subject: [PATCH 05/10] fix 500 error on pagination --- isso/views/comments.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/isso/views/comments.py b/isso/views/comments.py index df1eebe..7dfd423 100644 --- a/isso/views/comments.py +++ b/isso/views/comments.py @@ -519,9 +519,9 @@ class API(object): if not data or not data['logged']: return render_template('login.html') page_size = 100 - page = req.args.get('page', 0) + page = int(req.args.get('page', 0)) order_by = req.args.get('order_by', "id") - mode = req.args.get('mode', 2) + mode = int(req.args.get('mode', 2)) comments = self.comments.fetchall(mode=mode, page=page, limit=page_size, order_by=order_by) From e3fddf4ae8e7de83323f4b535c7cd586b430efed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Latinier?= Date: Sun, 13 Nov 2016 23:20:47 +0100 Subject: [PATCH 06/10] add: orders in administration --- isso/db/comments.py | 16 +++++++++++----- isso/templates/admin.html | 22 +++++++++++++++++++--- isso/views/comments.py | 8 +++++--- 3 files changed, 35 insertions(+), 11 deletions(-) diff --git a/isso/db/comments.py b/isso/db/comments.py index 62cfad2..a66c248 100644 --- a/isso/db/comments.py +++ b/isso/db/comments.py @@ -110,7 +110,7 @@ class Comments: return dict(comment_count) def fetchall(self, mode=5, after=0, parent='any', order_by='id', - limit=100, page=0): + limit=100, page=0, asc=1): """ Return comments for admin with :param:`mode`. """ @@ -138,10 +138,16 @@ class Comments: # custom sanitization if order_by not in ['id', 'created', 'modified', 'likes', 'dislikes', 'tid']: - order_by = 'id' - sql.append('ORDER BY ') - sql.append('comments.' + order_by + ", comments.created") - sql.append(' DESC') + sql.append('ORDER BY ') + sql.append("comments.created") + if not asc: + sql.append(' DESC') + else: + sql.append('ORDER BY ') + sql.append('comments.' + order_by) + if not asc: + sql.append(' DESC') + sql.append(", comments.created") if limit: sql.append('LIMIT ?,?') diff --git a/isso/templates/admin.html b/isso/templates/admin.html index 9d10816..376aa59 100644 --- a/isso/templates/admin.html +++ b/isso/templates/admin.html @@ -61,17 +61,17 @@ function delete_com(com_id, hash) {
{% set thread_id = "no_id" %} diff --git a/isso/views/comments.py b/isso/views/comments.py index 7dfd423..9621d7d 100644 --- a/isso/views/comments.py +++ b/isso/views/comments.py @@ -520,11 +520,13 @@ class API(object): return render_template('login.html') page_size = 100 page = int(req.args.get('page', 0)) - order_by = req.args.get('order_by', "id") + order_by = req.args.get('order_by', None) + asc = int(req.args.get('asc', 1)) mode = int(req.args.get('mode', 2)) comments = self.comments.fetchall(mode=mode, page=page, limit=page_size, - order_by=order_by) + order_by=order_by, + asc=asc) comments_enriched = [] for comment in list(comments): comment['hash'] = self.isso.sign(comment['id']) @@ -535,4 +537,4 @@ class API(object): page=int(page), mode=int(mode), conf=self.conf, max_page=max_page, counts=comment_mode_count, - order_by=order_by) + order_by=order_by, asc=asc) From 2adb779fefa8f0aae10abc7e0da9ecb761088eab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Latinier?= Date: Tue, 6 Dec 2016 23:03:27 +0100 Subject: [PATCH 07/10] add: edit author/email/website/message --- isso/css/admin.css | 9 +++++ isso/templates/admin.html | 79 ++++++++++++++++++++++++++++++++++++--- isso/views/comments.py | 17 ++++++--- 3 files changed, 94 insertions(+), 11 deletions(-) diff --git a/isso/css/admin.css b/isso/css/admin.css index 5a434fc..c440528 100644 --- a/isso/css/admin.css +++ b/isso/css/admin.css @@ -123,3 +123,12 @@ a { float: left; margin-left: 2em; } +.editable { + border: 1px solid #aaa; + border-radius: 5px; + margin: 10px; + padding: 5px; +} +.hidden { + display: none; +} diff --git a/isso/templates/admin.html b/isso/templates/admin.html index 376aa59..12ac60c 100644 --- a/isso/templates/admin.html +++ b/isso/templates/admin.html @@ -39,12 +39,72 @@ function moderate(com_id, hash, action) { fade(document.getElementById("isso-" + com_id)); }}); } +function edit(com_id, hash, author, email, website, comment) { + ajax({method: "POST", + url: "/id/" + com_id + "/edit/" + hash, + data: JSON.stringify({text: comment, + author: author, + email: email, + website: website}), + success: function(ret){ + console.log("edit successed: ", ret);// TODO display some pretty stuff & update msg + }, + error: function(ret){ + console.log("Error: ", ret); // TODO flash msg/notif + }}); +} function validate_com(com_id, hash) { moderate(com_id, hash, "validate"); } function delete_com(com_id, hash) { moderate(com_id, hash, "delete"); } +function unset_editable(elt_id) { + var elt = document.getElementById(elt_id); + if (elt) { + elt.contentEditable = false; + elt.classList.remove("editable"); + } +} +function set_editable(elt_id) { + var elt = document.getElementById(elt_id); + if (elt) { + elt.contentEditable = true; + elt.classList.add("editable"); + } +} +function start_edit(com_id) { + var editable_elements = ['isso-author-' + com_id, + 'isso-email-' + com_id, + 'isso-website-' + com_id, + 'isso-text-' + com_id]; + for (var idx=0; idx <= editable_elements.length; idx++) { + set_editable(editable_elements[idx]); + } + document.getElementById('edit-btn-' + com_id).classList.toggle('hidden'); + document.getElementById('stop-edit-btn-' + com_id).classList.toggle('hidden'); + document.getElementById('send-edit-btn-' + com_id).classList.toggle('hidden'); +} +function stop_edit(com_id) { + var editable_elements = ['isso-author-' + com_id, + 'isso-email-' + com_id, + 'isso-website-' + com_id, + 'isso-text-' + com_id]; + for (var idx=0; idx <= editable_elements.length; idx++) { + unset_editable(editable_elements[idx]); + } + document.getElementById('edit-btn-' + com_id).classList.toggle('hidden'); + document.getElementById('stop-edit-btn-' + com_id).classList.toggle('hidden'); + document.getElementById('send-edit-btn-' + com_id).classList.toggle('hidden'); +} +function send_edit(com_id, hash) { + var author = document.getElementById('isso-author-' + com_id).textContent; + var email = document.getElementById('isso-email-' + com_id).textContent; + var website = document.getElementById('isso-website-' + com_id).textContent; + var comment = document.getElementById('isso-text-' + com_id).textContent; + edit(com_id, hash, author, email, website, comment); + stop_edit(com_id); +}
@@ -130,18 +190,22 @@ function delete_com(com_id, hash) {
{% if order_by != "tid" %} - Thread: {{comment.title}}
+
Thread: {{comment.title}}

{% endif %} {% if comment.author %} - {{comment.author}} + {{comment.author}} {% else %} - Anonymous + Anonymous {% endif %} {% if comment.email %} - + ({{comment.email}} ) + {% else %} + {% endif %} {% if comment.website %} - ({{comment.website}}) + ({{comment.website}} open) + {% else %} + {% endif %} @@ -159,13 +223,16 @@ function delete_com(com_id, hash) { {% if comment.mode == 4 %} HIDDEN. Original text:
{% endif %} - {{comment.text}} +
{{comment.text}}