Changeset 804
- Timestamp:
- 06/02/06 06:45:06 (3 years ago)
- Files:
-
- discussionplugin/0.9/setup.py (modified) (1 diff)
- discussionplugin/0.9/tracdiscussion/core.py (modified) (15 diffs)
- discussionplugin/0.9/tracdiscussion/htdocs/css/discussion.css (modified) (2 diffs)
- discussionplugin/0.9/tracdiscussion/templates/forum-list.cs (modified) (3 diffs)
- discussionplugin/0.9/tracdiscussion/templates/message-list.cs (modified) (6 diffs)
- discussionplugin/0.9/tracdiscussion/templates/topic-add.cs (modified) (1 diff)
- discussionplugin/0.9/tracdiscussion/templates/topic-list.cs (modified) (1 diff)
- discussionplugin/0.9/tracdiscussion/timeline.py (added)
- discussionplugin/0.9/tracdiscussion/webadmin.py (added)
- discussionplugin/0.9/tracdiscussion/wiki.py (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
discussionplugin/0.9/setup.py
r775 r804 11 11 entry_points = {'trac.plugins': ['TracDiscussion.core = tracdiscussion.core', 12 12 'TracDiscussion.init = tracdiscussion.init', 13 'TracDiscussion.wiki = tracdiscussion.wiki']}, 13 'TracDiscussion.wiki = tracdiscussion.wiki', 14 'TracDiscussion.timeline = tracdiscussion.timeline']}, 14 15 keywords = 'trac discussion', 15 16 author = 'Alec Thomas, Radek BartoÅ', discussionplugin/0.9/tracdiscussion/core.py
r790 r804 3 3 from trac.web.main import IRequestHandler 4 4 from trac.wiki import wiki_to_html, wiki_to_oneliner 5 from trac.Timeline import ITimelineEventProvider 6 from trac.perm import IPermissionRequestor 5 from trac.perm import IPermissionRequestor, PermissionError 7 6 from trac.util import Markup, format_datetime, pretty_timedelta 8 7 import re, os, time … … 10 9 class DiscussionCore(Component): 11 10 """ 12 The discussionmodule implements a message board, including wiki links to11 The core module implements a message board, including wiki links to 13 12 discussions, topics and messages. 14 13 """ … … 64 63 req.hdf['trac.href.discussion'] = self.env.href.discussion() 65 64 66 forum, topic, message, mode, action, reply = None, None,None, None, \67 None, None 65 forum, topic, message, mode, action, reply, is_moderator = None, None, \ 66 None, None, None, None, False 68 67 69 68 # Get action … … 81 80 if not forum: 82 81 raise TracError('No such forum %s' % req.args.get('forum')) 82 83 # Determine moderator rights. 84 is_moderator = (req.authname in forum['moderators']) or \ 85 req.perm.has_permission('DISCUSSION_MODIFY') 83 86 84 87 # Populate active topic … … 182 185 req.perm.assert_permission('DISCUSSION_VIEW') 183 186 184 # Get from values 187 if req.authname: 188 req.hdf['discussion.authname'] = req.authname 189 190 # Get form values 185 191 author = req.args.get('author') 186 192 body = req.args.get('body') … … 206 212 req.perm.assert_permission('DISCUSSION_MODERATE') 207 213 214 # Check if user can moderate 215 if not is_moderator: 216 raise PermissionError('Forum moderate') 217 208 218 # Delete message 209 219 self.delete_topic(cursor, forum['id'], topic['id']) … … 217 227 elif mode == 'message-list': 218 228 req.perm.assert_permission('DISCUSSION_VIEW') 229 230 if req.authname: 231 req.hdf['discussion.authname'] = req.authname 219 232 220 233 # Get form values … … 251 264 req.perm.assert_permission('DISCUSSION_MODERATE') 252 265 266 # Check if user can moderate 267 if not is_moderator: 268 raise PermissionError('Forum moderate') 269 253 270 # Delete message 254 271 self.delete_message(cursor, forum['id'], topic['id'], reply) … … 263 280 req.hdf['discussion.message'] = message 264 281 req.hdf['discussion.mode'] = mode 282 req.hdf['discussion.is_moderator'] = is_moderator 265 283 db.commit() 266 284 return mode + '.cs', None … … 269 287 def get_message(self, cursor, id, req): 270 288 columns = ('id', 'forum', 'topic', 'replyto', 'time', 'author', 'body') 271 cursor.execute('SELECT id, forum, topic, replyto, time, author, body ,'272 'FROM message WHERE id =%s', [id])289 cursor.execute('SELECT id, forum, topic, replyto, time, author, body ' 290 'FROM message WHERE id = %s' % (id)) 273 291 for row in cursor: 274 292 row = dict(zip(columns, row)) … … 281 299 columns = ('id', 'forum', 'time', 'subject', 'body', 'author') 282 300 cursor.execute('SELECT id, forum, time, subject, body, author FROM' 283 ' topic WHERE id =%s', [id])301 ' topic WHERE id = %s' % (id)) 284 302 for row in cursor: 285 303 row = dict(zip(columns, row)) … … 292 310 columns = ('name', 'moderators', 'id', 'time', 'subject', 'description') 293 311 cursor.execute('SELECT name, moderators, id, time, subject, description' 294 ' FROM forum WHERE id = %s' , [id])312 ' FROM forum WHERE id = %s' % (id)) 295 313 for row in cursor: 296 314 row = dict(zip(columns, row)) … … 302 320 def get_forums(self, cursor, req): 303 321 columns = ('moderators', 'id', 'time', 'subject', 'name', 304 'description', 'topics', 'replies', 'lastreply' )322 'description', 'topics', 'replies', 'lastreply', 'lasttopic') 305 323 cursor.execute('SELECT moderators, id, time, subject, name,' 306 324 ' description, (SELECT COUNT(id) FROM topic t WHERE' 307 325 ' t.forum = forum.id), (SELECT COUNT(id) FROM message m WHERE m.forum' 308 326 ' = forum.id), (SELECT MAX(time) FROM message m WHERE m.forum =' 309 ' forum.id) FROM forum ORDER BY subject') 327 ' forum.id), (SELECT MAX(time) FROM topic t WHERE t.forum = forum.id)' 328 ' FROM forum ORDER BY subject') 310 329 forums = [] 311 330 for row in cursor: … … 317 336 else: 318 337 row['lastreply'] = 'No replies' 338 if row['lasttopic']: 339 row['lasttopic'] = pretty_timedelta(row['lasttopic']) 340 else: 341 row['lasttopic'] = 'No topics' 319 342 row['time'] = format_datetime(row['time']) 320 343 forums.append(row) … … 327 350 ' COUNT(id) FROM message m WHERE m.topic = topic.id), (SELECT' 328 351 ' MAX(time) FROM message m WHERE m.topic = topic.id) FROM topic' 329 ' WHERE forum = %s ORDER BY time' , [forum])352 ' WHERE forum = %s ORDER BY time' % (forum)) 330 353 topics = [] 331 354 for row in cursor: discussionplugin/0.9/tracdiscussion/htdocs/css/discussion.css
r790 r804 6 6 7 7 /* Forum list */ 8 .forum-list t d8 .forum-list tr > td 9 9 { 10 10 margin: 0em !important; … … 13 13 } 14 14 15 .forum-list .subject, .forum-list .description15 .forum-list tr > td > a 16 16 { 17 margin: 0.5em; 18 } 19 20 .forum-list .table 21 { 22 display: table; 17 display: block; 23 18 height: 100%; 24 width: 100%; 19 padding: 0.5em; 20 margin: 0em; 25 21 border: none; 26 22 } 27 23 28 .forum-list .row 29 { 30 display: table-row; 31 height: 100%; 32 } 33 34 .forum-list .cell 35 { 36 display: table-cell; 37 vertical-align: middle; 38 } 39 40 .forum-list td.moderators, .forum-list td.lastreply, .forum-list td.founded, 41 .forum-list td.topics, .forum-list td.replies 24 .forum-list td.moderators, .forum-list td.lasttopic, .forum-list td.lastreply, 25 .forum-list td.founded, .forum-list td.topics, .forum-list td.replies 42 26 { 43 27 text-align: center; discussionplugin/0.9/tracdiscussion/templates/forum-list.cs
r790 r804 1 1 <?cs include "discussion-header.cs" ?> 2 2 3 <h1>Forum Index</h1>3 <h1>Forum List</h1> 4 4 <table class="listing"> 5 5 <thead> … … 7 7 <th class="subject">Forum</th> 8 8 <th class="moderators">Moderators</th> 9 <th class="lasttopic">Last Topic</th> 9 10 <th class="lastreply">Last Reply</th> 10 11 <th class="founded">Founded</th> … … 23 24 </td> 24 25 <td class="moderators"> 25 <a class="table" href="<?cs var:trac.href.discussion ?>/<?cs var:forum.id ?>"> 26 <div class="row"> 27 <div class="cell"><?cs var:forum.moderators ?></div> 28 </div> 26 <a href="<?cs var:trac.href.discussion ?>/<?cs var:forum.id ?>"> 27 <div class="moderators"><?cs var:forum.moderators ?></div> 28 </a> 29 </td> 30 <td class="lasttopic"> 31 <a href="<?cs var:trac.href.discussion ?>/<?cs var:forum.id ?>"> 32 <div class="lasttopic"><?cs var:forum.lasttopic ?></div> 29 33 </a> 30 34 </td> 31 35 <td class="lastreply"> 32 <a class="table" href="<?cs var:trac.href.discussion ?>/<?cs var:forum.id ?>"> 33 <div class="row"> 34 <div class="cell"><?cs var:forum.lastreply ?></div> 35 </div> 36 <a href="<?cs var:trac.href.discussion ?>/<?cs var:forum.id ?>"> 37 <div class="lastreply"><?cs var:forum.lastreply ?></div> 36 38 </a> 37 39 </td> 38 40 <td class="founded"> 39 <a class="table" href="<?cs var:trac.href.discussion ?>/<?cs var:forum.id ?>"> 40 <div class="row"> 41 <div class="cell"><?cs var:forum.time ?></div> 42 </div> 41 <a href="<?cs var:trac.href.discussion ?>/<?cs var:forum.id ?>"> 42 <div class="founded"><?cs var:forum.time ?></div> 43 43 </a> 44 44 </td> 45 45 <td class="topics"> 46 <a class="table" href="<?cs var:trac.href.discussion ?>/<?cs var:forum.id ?>"> 47 <div class="row"> 48 <div class="cell"><?cs var:forum.topics ?></div> 49 </div> 46 <a href="<?cs var:trac.href.discussion ?>/<?cs var:forum.id ?>"> 47 <div class="topics"><?cs var:forum.topics ?></div> 50 48 </a> 51 49 </td> 52 50 <td class="replies"> 53 <a class="table" href="<?cs var:trac.href.discussion ?>/<?cs var:forum.id ?>"> 54 <div class="row"> 55 <div class="cell"><?cs var:forum.replies ?></div> 56 </div> 51 <a href="<?cs var:trac.href.discussion ?>/<?cs var:forum.id ?>"> 52 <div class="replies"><?cs var:forum.replies ?></div> 57 53 </a> 58 54 </td> discussionplugin/0.9/tracdiscussion/templates/message-list.cs
r790 r804 3 3 <?cs def:display_preview() ?> 4 4 <li class="preview"> 5 <a name="preview"></a> 5 6 <div class="body"> 6 7 <?cs var:discussion.body ?> … … 12 13 <?cs /def ?> 13 14 14 <?cs def:display_form() ?>15 <?cs def:display_form() ?> 15 16 <li class="reply"> 16 17 <fieldset> 18 <a name="reply"></a> 17 19 <legend> 18 20 Reply: 19 21 </legend> 20 <form method="post" action="<?cs var:trac.href.discussion ?>/<?cs var:discussion.forum.id ?>/<?cs var:discussion.topic.id ?> ">22 <form method="post" action="<?cs var:trac.href.discussion ?>/<?cs var:discussion.forum.id ?>/<?cs var:discussion.topic.id ?>#preview"> 21 23 <div class="field"> 22 24 <label for="author">Author:</label><br/> 23 <input type="text" name="author" value="<?cs var:args.author ?>"/> 25 <?cs if:args.author ?> 26 <input type="text" name="author" value="<?cs var:args.author ?>"/><br/> 27 <?cs else ?> 28 <input type="text" name="author" value="<?cs var:discussion.authname ?>"/><br/> 29 <?cs /if ?> 24 30 </div> 25 31 <div class="field"> … … 42 48 <?cs each:message = messages ?> 43 49 <li> 50 <a name="<?cs var:message.id ?>"></a> 44 51 <div class="body"> 45 52 <?cs var:message.body ?> 46 53 </div> 47 54 <div class="controls"> 48 <a href="<?cs var:trac.href.discussion ?>/<?cs var:discussion.forum.id ?>/<?cs var:discussion.topic.id ?> ?action=add;reply=<?cs var:message.id ?>">Reply</a>49 <?cs if:trac.acl.DISCUSSION_MODERATE ?>55 <a href="<?cs var:trac.href.discussion ?>/<?cs var:discussion.forum.id ?>/<?cs var:discussion.topic.id ?>#reply?action=add;reply=<?cs var:message.id ?>">Reply</a> 56 <?cs if:trac.acl.DISCUSSION_MODERATE && discussion.is_moderator ?> 50 57 <a href="<?cs var:trac.href.discussion ?>/<?cs var:discussion.forum.id ?>/<?cs var:discussion.topic.id ?>?action=delete;reply=<?cs var:message.id ?>">Delete</a> 51 58 <?cs /if ?> … … 69 76 <?cs /def ?> 70 77 71 <h1 class="forum-subject"> 72 <?cs var:discussion.forum.subject ?> 73 </h1> 78 <h1 class="forum-subject"><?cs var:discussion.forum.subject ?> - Message List</h1> 79 <a name="-1"></a> 74 80 <div class="topic"> 75 81 <div class="header"> … … 81 87 </div> 82 88 <div class="controls"> 83 <a href="<?cs var:trac.href.discussion ?>/<?cs var:discussion.forum.id ?>/<?cs var:discussion.topic.id ?> ?action=add;reply=-1">Reply</a>89 <a href="<?cs var:trac.href.discussion ?>/<?cs var:discussion.forum.id ?>/<?cs var:discussion.topic.id ?>#reply?action=add;reply=-1">Reply</a> 84 90 </div> 85 91 <div class="author"> … … 102 108 </div> 103 109 104 <?cs if:trac.acl.DISCUSSION_MODERATE ?>110 <?cs if:trac.acl.DISCUSSION_MODERATE && discussion.is_moderator ?> 105 111 <div class="buttons"> 106 112 <form method="post" action="<?cs var:trac.href.discussion ?>/<?cs var:discussion.forum.id ?>/<?cs var:discussion.topic.id ?>"> discussionplugin/0.9/tracdiscussion/templates/topic-add.cs
r790 r804 28 28 <div class="field"> 29 29 <label for="author">Author:</label><br/> 30 <input type="text" name="author" value="<?cs var:args.author ?>"/><br/> 30 <?cs if:args.author ?> 31 <input type="text" name="author" value="<?cs var:args.author ?>"/><br/> 32 <?cs else ?> 33 <input type="text" name="author" value="<?cs var:discussion.authname ?>"/><br/> 34 <?cs /if ?> 31 35 </div> 32 36 <div class="field"> discussionplugin/0.9/tracdiscussion/templates/topic-list.cs
r790 r804 1 1 <?cs include "discussion-header.cs" ?> 2 2 3 <h1> 4 <?cs var:discussion.forum.subject ?> 5 </h1> 6 <div class="forum-description"> 7 <?cs var:discussion.forum.description ?> 8 </div> 3 <h1><?cs var:discussion.forum.subject ?> - Topic List</h1> 4 <div class="forum-description"><?cs var:discussion.forum.description ?></div> 9 5 <table class="listing"> 10 6 <thead> discussionplugin/0.9/tracdiscussion/wiki.py
r72 r804 3 3 4 4 class DiscussionWiki(Component): 5 """ 6 The wiki module implements macros for forums, topics and messages 7 referencing. 8 """ 5 9 implements(IWikiSyntaxProvider) 6 10 … … 16 20 # Core code 17 21 def _discussion_link(self, formatter, ns, params, label): 18 if ns != 'forum': 19 try: 20 id = int(params) 21 except ValueError: 22 return '<div class="system-message"><strong>Error:</strong> Invalid %s id "%s"</div>\n' % (ns, params) 23 else: 24 id = params 22 id = params 23 25 24 db = self.env.get_db_cnx() 26 25 cursor = db.cursor() 27 26 if ns == 'forum': 28 cursor.execute('SELECT subject FROM forum WHERE name=%s', id) 29 row = cursor.fetchone() 30 if row: 31 subject = row[0] 32 return '<a href="%s/%s" title="%s">%s</a>' % (self.env.href.discussion(), id, subject, label) 33 else: 34 return '<a href="%s/%s" class="missing">%s?</a>' % (self.env.href.discussion(), id, label) 27 columns = ('subject',) 28 cursor.execute('SELECT subject FROM forum WHERE id = %s', id) 29 for row in cursor: 30 row = dict(zip(columns, row)) 31 return '<a href="%s/%s" title="%s">%s</a>' % ( 32 self.env.href.discussion(), id, row['subject'], label) 33 return '<a href="%s/%s" class="missing">%s?</a>' % ( 34 self.env.href.discussion(), id, label) 35 35 elif ns == 'topic': 36 cursor.execute('SELECT (SELECT name FROM forum WHERE id=topic.forum), (SELECT subject FROM forum WHERE id=topic.forum), subject FROM topic WHERE id=%i', id) 37 row = cursor.fetchone() 38 if row: 36 columns = ('forum', 'forum_subject', 'subject') 37 cursor.execute('SELECT forum, (SELECT subject FROM forum WHERE id =' 38 ' topic.forum), subject FROM topic WHERE id = %s', id) 39 for row in cursor: 40 row = dict(zip(columns, row)) 39 41 forum, forum_subject, subject = row 40 return '<a href="%s/%s/%s" title="%s: %s">%s</a>' % (self.env.href.discussion(), forum, id, forum_subject, subject, label) 42 return '<a href="%s/%s/%s#-1" title="%s: %s">%s</a>' % ( 43 self.env.href.discussion(), row['forum'], id, 44 row['forum_subject'], row['subject'], label) 45 return '<a href="%s/%s" class="missing">%s?</a>' % ( 46 self.env.href.discussion(), id, label) 41 47 elif ns == 'message': 42 cursor.execute('SELECT (SELECT name FROM forum WHERE id=message.forum), topic, (SELECT subject FROM forum WHERE id=message.forum), (SELECT subject FROM topic WHERE id=message.topic) FROM message WHERE id=%i', id) 43 row = cursor.fetchone() 44 if row: 45 forum, topic, forum_subject, subject = row 46 return '<a href="%s/%s/%s/%s" title="%s: %s">%s</a>' % (self.env.href.discussion(), forum, topic, id, forum_subject, subject, label) 47 return '<a href="%s" class="missing">%s?</a>' % (self.env.href.discussion(), label) 48 columns = ('forum', 'topic', 'forum_subject', 'subject') 49 cursor.execute('SELECT forum, topic, (SELECT subject FROM forum' 50 ' WHERE id = message.forum), (SELECT subject FROM topic WHERE' 51 ' id = message.topic) FROM message WHERE id = %s' % (id)) 52 for row in cursor: 53 row = dict(zip(columns, row)) 54 return '<a href="%s/%s/%s/%s#%s" title="%s: %s">%s</a>' % ( 55 self.env.href.discussion(), row['forum'], row['topic'], id, 56 id, row['forum_subject'], row['subject'], label) 57 return '<a href="%s/%s" class="missing">%s?</a>' % ( 58 self.env.href.discussion(), id, label) 59 return '<a href="%s" class="missing">%s?</a>' % ( 60 self.env.href.discussion(), label)
