Author: blackbird Date: 2007-07-19 18:44:45 +0200 (Thu, 19 Jul 2007) New Revision: 5382 Added: trunk/sandbox/py-rest-doc/sphinx/templates/_commentform.html trunk/sandbox/py-rest-doc/sphinx/templates/commentform.html Modified: trunk/sandbox/py-rest-doc/sphinx/style/default.css trunk/sandbox/py-rest-doc/sphinx/style/doctools.js trunk/sandbox/py-rest-doc/sphinx/templates/comments.html trunk/sandbox/py-rest-doc/sphinx/web/application.py trunk/sandbox/py-rest-doc/sphinx/web/wsgiutil.py Log: working on the comment system Modified: trunk/sandbox/py-rest-doc/sphinx/style/default.css =================================================================== --- trunk/sandbox/py-rest-doc/sphinx/style/default.css 2007-07-18 23:08:53 UTC (rev 5381) +++ trunk/sandbox/py-rest-doc/sphinx/style/default.css 2007-07-19 16:44:45 UTC (rev 5382) @@ -275,8 +275,8 @@ position: absolute; left: 400px; top: 200px; - width: 400px; - height: 300px; + width: 600px; + height: 600px; background-color: #333; border: 1px solid black; display: none; Modified: trunk/sandbox/py-rest-doc/sphinx/style/doctools.js =================================================================== --- trunk/sandbox/py-rest-doc/sphinx/style/doctools.js 2007-07-18 23:08:53 UTC (rev 5381) +++ trunk/sandbox/py-rest-doc/sphinx/style/doctools.js 2007-07-19 16:44:45 UTC (rev 5382) @@ -172,7 +172,7 @@ * make the url absolute */ makeURL : function(relativeURL) { - return DOCUMENTATION_OPTIONS.URL_ROOT + relativeURL; + return DOCUMENTATION_OPTIONS.URL_ROOT + '/' + relativeURL; }, /** @@ -182,8 +182,8 @@ var openWindows = {}; var Window = function(sectionID) { - var url = Documentation.makeURL('@comments/' + DOCUMENTATION_OPTIONS.SOURCE - + '/?target=' + $.urlencode(sectionID) + '&mode=plain'); + this.url = Documentation.makeURL('@comments/' + DOCUMENTATION_OPTIONS.SOURCE + + '/?target=' + $.urlencode(sectionID) + '&mode=ajax'); this.sectionID = sectionID; this.root = $('<div class="commentwindow"></div>'); @@ -197,9 +197,38 @@ }); this.root.fadeIn('slow'); - this.body.load(url); + this.updateView(); }; + Window.prototype.updateView = function(data) { + var self = this; + function update(data) { + self.body.html(data.body); + $('form', self.body).submit(function() { + self.onFormSubmit(this); + return false; + }); + } + + if (typeof data == 'undefined') + $.getJSON(this.url, function(json) { update(json); }); + else + update(data); + } + + Window.prototype.getFormValue = function(name) { + return $('input[@name="' + name + '"]')[0].value; + } + + Window.prototype.onFormSubmit = function(form) { + $.post(this.url, { + author: this.getFormValue('author'), + author_mail: this.getFormValue('author_mail'), + title: this.getFormValue('title'), + comment_body: this.getFormValue('comment_body') + }, function(data) { this.updateView(data); }); + } + Window.prototype.close = function() { delete openWindows[this.sectionID]; this.root.fadeOut('slow', function() { Added: trunk/sandbox/py-rest-doc/sphinx/templates/_commentform.html =================================================================== --- trunk/sandbox/py-rest-doc/sphinx/templates/_commentform.html 2007-07-18 23:08:53 UTC (rev 5381) +++ trunk/sandbox/py-rest-doc/sphinx/templates/_commentform.html 2007-07-19 16:44:45 UTC (rev 5382) @@ -0,0 +1,23 @@ + <form action="#comments-new-comment" method="post"> + {% if comments_form.error %} + <div class="error">{{ comments_form.error|e }}</div> + {% endif %} + <input type="hidden" name="target" value="{{ comments_form.target|e(true) }}"> + <p>Note: you can also <a href="{{ pathto('@edit/' + sourcename)|e }}">suggest + changes</a> to the official documentation text.</p> + <dl> + <dt>Name:</dt> + <dd><input type="text" size="24" name="author" value="{{ comments_form.author|e(true) }}"></dd> + <dt>E-Mail Address:</dt> + <dd><input type="text" size="24" name="author_mail" value="{{ comments_form.author_mail|e(true) }}"></dd> + <dt>Comment Title:</dt> + <dd><input type="text" size="36" name="title" value="{{ comments_form.title|e(true) }}"></dd> + </dl> + <input type="text" size="12" name="homepage" id="homepage"> + <textarea name="comment_body" rows="7" cols="50">{{ comments_form.comment_body|e }}</textarea> + <div class="actions"> + <input type="submit" value="Submit comment"> + <input type="submit" name="preview" value="Preview"> + <input type="reset" value="Reset form"> + </div> + </form> Added: trunk/sandbox/py-rest-doc/sphinx/templates/commentform.html =================================================================== --- trunk/sandbox/py-rest-doc/sphinx/templates/commentform.html 2007-07-18 23:08:53 UTC (rev 5381) +++ trunk/sandbox/py-rest-doc/sphinx/templates/commentform.html 2007-07-19 16:44:45 UTC (rev 5382) @@ -0,0 +1,26 @@ +{% extends "layout.html" %} +{% block body %} + <div id="new-commment-box"> + <h4 id="comments-new-comment">New Comment</h4> + {{ form }} + <div class="help"> + <p> + <strong>You can format a comment using the + following syntax elements provided:</strong> + </p> + <p> + `code` / ``code too`` / **strong** / + *emphasized* / !!!important!!! / + [[link_target Link Title]] / + [[link_target_only]] / <code>code block with + syntax highlighting</code> / <quote>some + quoted text</quote>. + </p> + <p> + HTML is not supported, relative link targets are treated as + quicklinks and code blocks that start with ">>>" are + highlighted as interactive python sessions. + </p> + </div> + </div> +{% endblock %} Modified: trunk/sandbox/py-rest-doc/sphinx/templates/comments.html =================================================================== --- trunk/sandbox/py-rest-doc/sphinx/templates/comments.html 2007-07-18 23:08:53 UTC (rev 5381) +++ trunk/sandbox/py-rest-doc/sphinx/templates/comments.html 2007-07-19 16:44:45 UTC (rev 5382) @@ -26,51 +26,4 @@ <a href="#">#</a></p> </div> {% endif %} - - <div class="new-comment-box" id="new-comment-box" style="display: none"> - <h4 id="comments-new-comment">New Comment</h4> - <form action="#comments-new-comment" method="post"> - {% if comments_form.error %} - <div class="error">{{ comments_form.error|e }}</div> - {% endif %} - <p>Note: you can also <a href="{{ pathto('@edit/' + sourcename)|e }}">suggest - changes</a> to the official documentation text.</p> - <dl> - <dt>Name:</dt> - <dd><input type="text" size="24" name="author" value="{{ comments_form.author|e(true) }}"></dd> - <dt>E-Mail Address:</dt> - <dd><input type="text" size="24" name="author_mail" value="{{ comments_form.author_mail|e(true) }}"></dd> - <dt>Comment Title:</dt> - <dd><input type="text" size="36" name="title" value="{{ comments_form.title|e(true) }}"></dd> - <dt>Descname (XXX to be removed):</dt> - <dd><input type="text" size="36" name="descname" value=""></dd> - </dl> - <input type="text" size="12" name="homepage" id="homepage"> - <textarea name="comment_body" rows="7" cols="50">{{ comments_form.comment_body|e }}</textarea> - <div class="help"> - <p> - <strong>You can format a comment using the - following syntax elements provided:</strong> - </p> - <p> - `code` / ``code too`` / **strong** / - *emphasized* / !!!important!!! / - [[link_target Link Title]] / - [[link_target_only]] / <code>code block with - syntax highlighting</code> / <quote>some - quoted text</quote>. - </p> - <p> - HTML is not supported, relative link targets are treated as - quicklinks and code blocks that start with ">>>" are - highlighted as interactive python sessions. - </p> - </div> - <div class="actions"> - <input type="submit" value="Submit comment"> - <input type="submit" name="preview" value="Preview"> - <input type="reset" value="Reset form"> - </div> - </form> - </div> - </div> \ No newline at end of file + </div> Modified: trunk/sandbox/py-rest-doc/sphinx/web/application.py =================================================================== --- trunk/sandbox/py-rest-doc/sphinx/web/application.py 2007-07-18 23:08:53 UTC (rev 5381) +++ trunk/sandbox/py-rest-doc/sphinx/web/application.py 2007-07-19 16:44:45 UTC (rev 5382) @@ -36,7 +36,7 @@ from .antispam import AntiSpam from .database import connect, set_connection, Comment from .wsgiutil import Request, Response, RedirectResponse, \ - SharedDataMiddleware, NotFound, get_base_uri + JSONResponse, SharedDataMiddleware, NotFound, get_base_uri from ..util import relative_uri, shorten_result from ..search import SearchFrontend @@ -379,55 +379,70 @@ yield render_template(req, 'modindex.html', self.globalcontext, context) + def show_comment_form(self, req, page_id): + """ + Show the "new comment" form. + """ + ajax_mode = req.args.get('mode') == 'ajax' + target = req.args.get('target') + page_comment_mode = not target - def handle_new_comment(self, req, context, page_id): - # XXX - # default values for the comment form - title = comment_body = author = author_mail = '' - form_error = None - preview = None - + form_error = preview = None title = req.form.get('title', '').strip() author = req.form.get('author', '').strip() author_mail = req.form.get('author_mail', '') comment_body = req.form.get('comment_body', '') fields = (title, author, author_mail, comment_body) - if req.form.get('preview'): - preview = Comment(page_id, title, author, author_mail, - comment_body) - # 'homepage' is a forbidden field to thwart bots - elif req.form.get('homepage') or self.antispam.is_spam(fields): - form_error = 'Your text contains blocked URLs or words.' - else: - if not all(fields): - form_error = 'You have to fill out all fields.' - elif _mail_re.search(author_mail) is None: - form_error = 'You have to provide a valid e-mail address.' - elif len(comment_body) < 20: - form_error = 'You comment is too short ' \ - '(must have at least 20 characters).' + if req.method == 'POST': + if req.form.get('preview'): + preview = Comment(page_id, title, author, author_mail, + comment_body) + # 'homepage' is a forbidden field to thwart bots + elif req.form.get('homepage') or self.antispam.is_spam(fields): + form_error = 'Your text contains blocked URLs or words.' else: - # '|none' can stay since it doesn't include comments - self.cache.pop(page_id+'|inline', None) - self.cache.pop(page_id+'|bottom', None) - comment = Comment(page_id, req.form.get('descname'), - title, author, author_mail, - comment_body) - comment.save() - return RedirectResponse(comment.url) + if not all(fields): + form_error = 'You have to fill out all fields.' + elif _mail_re.search(author_mail) is None: + form_error = 'You have to provide a valid e-mail address.' + elif len(comment_body) < 20: + form_error = 'You comment is too short ' \ + '(must have at least 20 characters).' + else: + # '|none' can stay since it doesn't include comments + self.cache.pop(page_id+'|inline', None) + self.cache.pop(page_id+'|bottom', None) + comment = Comment(page_id, target, + title, author, author_mail, + comment_body) + comment.save() + if ajax_mode: + return JSONResponse({'posted': True, 'error': False}) + return RedirectResponse(comment.url) - context.update( - preview = preview, - comments_form = { - 'title': title, - 'author': author, - 'author_mail': author_mail, - 'comment_body': comment_body, - 'error': form_error, - }, - ) + output = render_template(req, '_commentform.html', { + 'ajax_mode': ajax_mode, + 'preview': preview, + 'comments_form': { + 'target': target, + 'title': title, + 'author': author, + 'author_mail': author_mail, + 'comment_body': comment_body, + 'error': form_error + } + }) + if ajax_mode: + return JSONResponse({ + 'body': output, + 'error': bool(form_error), + 'posted': False + }) + return Response(render_template(req, 'commentform.html', { + 'form': output + })) def _insert_comments(self, page_id, context, mode): """ @@ -482,14 +497,6 @@ # comments enabled? comments = self.env.metadata[page_id].get('comments_enabled', True) - # do form validation and comment saving if the request method is POST. - # XXX different URLs - if comments and req.method == 'POST': - resp = self.handle_new_comment(req, context, page_id) - if resp: - # may be a redirecting response - return - # how does the user want to view comments? commentmode = req.session.get('comments', 'inline') if comments else '' @@ -703,6 +710,9 @@ # suggest changes submit elif url[:8] == '@submit/': resp = self.submit_changes(req, url[8:]) + # show that comment form + elif url[:10] == '@comments/': + resp = self.show_comment_form(req, url[10:]) # comments RSS feed elif url[:5] == '@rss/': resp = self.comments_feed(req, url[5:]) Modified: trunk/sandbox/py-rest-doc/sphinx/web/wsgiutil.py =================================================================== --- trunk/sandbox/py-rest-doc/sphinx/web/wsgiutil.py 2007-07-18 23:08:53 UTC (rev 5381) +++ trunk/sandbox/py-rest-doc/sphinx/web/wsgiutil.py 2007-07-19 16:44:45 UTC (rev 5382) @@ -24,6 +24,7 @@ from cStringIO import StringIO from .util import lazy_property +from .json import dump_json HTTP_STATUS_CODES = { @@ -638,11 +639,17 @@ def __call__(self, environ, start_response): url = get_base_uri(environ) + self.target_url - self.headers['Location'] = url return super(RedirectResponse, self).__call__(environ, start_response) +class JSONResponse(Response): + + def __init__(self, data): + assert not isinstance(data, list), 'list unsafe for json dumping' + super(JSONResponse, self).__init__(dump_json(data), mimetype='text/javascript') + + class SharedDataMiddleware(object): """ Redirects calls to an folder with static data. |