/kai/templates/widgets.mako

https://bitbucket.org/bbangert/kai/ · Mako · 167 lines · 158 code · 3 blank · 6 comment · 17 complexity · 133c896281aecb50ec3dacd0a0250714 MD5 · raw file

  1. <%!
  2. from datetime import datetime
  3. from md5 import md5
  4. import pytz
  5. from kai.model import Comment, forms
  6. %>
  7. <%def name="show_comments(doc_id, poster_id=None, message=None)">
  8. <%
  9. total = Comment.total_comments(doc_id)
  10. if total > 0:
  11. comments = list(Comment.by_time(c.db, startkey=[doc_id], endkey=[doc_id, {}]))
  12. else:
  13. comments = []
  14. %>
  15. <div class="comments">
  16. <a name="comments"></a>
  17. <h2>Comments <span class="subtle">(${total})</span></h2>
  18. % for comment in comments:
  19. ${show_comment(comment, extra_class=(poster_id and poster_id == comment.human_id and 'highlight'))}
  20. % endfor
  21. % if message:
  22. <p class="suggest_comment">${message}</p>
  23. % endif
  24. % if c.user:
  25. <div style="display: none;" id="comment_preview">&nbsp;</div>
  26. <div class="comment_format">${h.link_to('Formatting Quick Reference', url="http://hobix.com/textile/quick.html")}</div>
  27. ${forms.comment_form.display(action='#') | n}
  28. % else:
  29. <p>You must ${h.link_to(_('login'), url=url('account_login', redir=url.current()))} before you can comment.</p>
  30. % endif
  31. </div>
  32. </%def>
  33. ##
  34. <%def name="show_comment(comment, extra_class=None)">
  35. <a name="${comment.id}" />
  36. <div class="comment ${extra_class or ''}">
  37. ${user_post(comment.displayname, comment.email, comment.created, 'comments')}
  38. % if c.user and c.user.in_group('admin'):
  39. <div class="comment_delete commentid_${comment.id}">${h.link_to('Delete this comment', url='#', id_='comment_delete')}</div>
  40. % endif
  41. <div class="content">${h.textilize(comment.content)}</div>
  42. </div>
  43. </%def>
  44. ##
  45. <%def name="user_post(displayname, email, post_date, extra_classes='')">
  46. <div class="${extra_classes} user_post">
  47. <div class="user_icon">\
  48. % if email:
  49. <img src="http://www.gravatar.com/avatar/${md5(email).hexdigest()}?s=40">
  50. % else:
  51. <img src="http://www.gravatar.com/avatar/3b3be63a4c2a439b013787725dfce802?s=40">
  52. % endif
  53. </div>
  54. <div class="username">${displayname or 'Anonymous'}</div>
  55. <div class="posted">${format_timestamp(post_date)}</div>
  56. </div>
  57. </%def>
  58. ##
  59. <%def name="format_timestamp(date)">
  60. <%
  61. diff = datetime.utcnow() - date
  62. date = pytz.UTC.localize(date).astimezone(timezone)
  63. now = pytz.UTC.localize(datetime.utcnow()).astimezone(timezone)
  64. %>
  65. % if diff.days < 3:
  66. ${h.distance_of_time_in_words(date, now, granularity='minute')} ago
  67. % else:
  68. ${format.datetime(date)}
  69. % endif
  70. </%def>
  71. ##
  72. <%def name="comment_js(doc_id)">
  73. $('input#preview').click(function() {
  74. var content = $('#comment_form_comment')[0].value;
  75. var preview_url = '${url('preview_comment')}';
  76. $.ajax({
  77. data: {content:content},
  78. type: "POST",
  79. url: preview_url,
  80. success: function(data, textStatus) {
  81. $('#comment_preview').html(data).slideDown();
  82. }
  83. });
  84. return false;
  85. });
  86. $('input#submit').click(function() {
  87. var content = $('#comment_form_comment')[0].value;
  88. var submit_url = '${url('post_comment', doc_id=doc_id)}';
  89. $.ajax({
  90. data: {content:content},
  91. type: "POST",
  92. url: submit_url,
  93. success: function(data, textStatus) {
  94. window.location = location.pathname;
  95. }
  96. });
  97. return false;
  98. });
  99. % if c.user and c.user.in_group('admin'):
  100. $('div.comment_delete a').click(function() {
  101. var answer = window.confirm("Are you sure you want to delete this comment?");
  102. var delete_url = '/comment/' + $(this).parent().attr('class').replace(/^.*commentid_(\w*)$/,'$1');
  103. if (answer) {
  104. $.ajax({
  105. data: {'_method':'DELETE'},
  106. type: "POST",
  107. url: delete_url,
  108. success: function(data, textStatus) {
  109. window.location = location.pathname;
  110. }
  111. });
  112. }
  113. return false;
  114. });
  115. % endif
  116. </%def>
  117. ##
  118. <%def name="comment_link(title, comment_id, doc, type, urlonly=False)">
  119. <%
  120. link = '#'
  121. if type == 'Documentation':
  122. link = url('doc_view', version=doc['version'], language=doc['language'], url=doc['current_page_name'] + '/', anchor=comment_id)
  123. elif type == 'Traceback':
  124. link = url('traceback', id=doc['_id'], anchor=comment_id)
  125. elif type == 'Paste':
  126. link = url('paste', id=doc.get(old_id, doc['_id']), anchor=comment_id)
  127. elif type == 'Snippet':
  128. link = url('snippet', id=doc['slug'], anchor=comment_id)
  129. %>
  130. % if urlonly:
  131. ${link}
  132. % else:
  133. ${h.link_to(title, url=link)}
  134. % endif
  135. </%def>
  136. ##
  137. <%def name="pager(start, lst, total, keyname)">
  138. <%
  139. start = int(start)
  140. if total < start + 9:
  141. end = total
  142. else:
  143. end = start + 9
  144. startkey = lst[-1]._data[keyname]
  145. if start > 10:
  146. prevkey = lst[0]._data[keyname]
  147. %>
  148. <div id="paging">\
  149. <div class="pger">
  150. % if start > 10:
  151. <a class="prev" href="${url.current(start=start-10, prevkey=prevkey)}">? Previous Page</a> |
  152. % else:
  153. <a class="prev">? Previous Page</a> |
  154. % endif
  155. \
  156. % if start + 9 < total:
  157. <a class="next" href="${url.current(start=start+10, startkey=startkey)}">Next Page ?</a>
  158. % else:
  159. <a class="next">Next Page ?</a>
  160. % endif
  161. </div>
  162. <div class="showing">Showing ${start}-${end} of ${total}</div>
  163. </div>
  164. </%def>