Changeset 804

Show
Ignore:
Timestamp:
06/02/06 06:45:06 (3 years ago)
Author:
Blackhex
Message:

DiscussionPlugin:

A lot of changes:

  • Display last topic time in message list.
  • Repair of wiki macros.
  • Anchors in message list.
  • Timeline events.
  • Authenticated user name filling.
  • Moderate can only users with DISCUSSION_MODIFY or (DISCUSSION_MODERATE and are moderators) permission.
Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • discussionplugin/0.9/setup.py

    r775 r804  
    1111  entry_points = {'trac.plugins': ['TracDiscussion.core = tracdiscussion.core', 
    1212    'TracDiscussion.init = tracdiscussion.init', 
    13     'TracDiscussion.wiki = tracdiscussion.wiki']}, 
     13    'TracDiscussion.wiki = tracdiscussion.wiki', 
     14    'TracDiscussion.timeline = tracdiscussion.timeline']}, 
    1415  keywords = 'trac discussion', 
    1516  author = 'Alec Thomas, Radek Bartoň', 
  • discussionplugin/0.9/tracdiscussion/core.py

    r790 r804  
    33from trac.web.main import IRequestHandler 
    44from trac.wiki import wiki_to_html, wiki_to_oneliner 
    5 from trac.Timeline import ITimelineEventProvider 
    6 from trac.perm import IPermissionRequestor 
     5from trac.perm import IPermissionRequestor, PermissionError 
    76from trac.util import Markup, format_datetime, pretty_timedelta 
    87import re, os, time 
     
    109class DiscussionCore(Component): 
    1110    """ 
    12         The discussion module implements a message board, including wiki links to 
     11        The core module implements a message board, including wiki links to 
    1312        discussions, topics and messages. 
    1413    """ 
     
    6463        req.hdf['trac.href.discussion'] = self.env.href.discussion() 
    6564 
    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 
    6867 
    6968        # Get action 
     
    8180            if not forum: 
    8281                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') 
    8386 
    8487        # Populate active topic 
     
    182185            req.perm.assert_permission('DISCUSSION_VIEW') 
    183186 
    184             # Get from values 
     187            if req.authname: 
     188                req.hdf['discussion.authname'] = req.authname 
     189 
     190            # Get form values 
    185191            author = req.args.get('author') 
    186192            body = req.args.get('body') 
     
    206212            req.perm.assert_permission('DISCUSSION_MODERATE') 
    207213 
     214            # Check if user can moderate 
     215            if not is_moderator: 
     216                raise PermissionError('Forum moderate') 
     217 
    208218            # Delete message 
    209219            self.delete_topic(cursor, forum['id'], topic['id']) 
     
    217227        elif mode == 'message-list': 
    218228            req.perm.assert_permission('DISCUSSION_VIEW') 
     229 
     230            if req.authname: 
     231                req.hdf['discussion.authname'] = req.authname 
    219232 
    220233            # Get form values 
     
    251264            req.perm.assert_permission('DISCUSSION_MODERATE') 
    252265 
     266            # Check if user can moderate 
     267            if not is_moderator: 
     268                raise PermissionError('Forum moderate') 
     269 
    253270            # Delete message 
    254271            self.delete_message(cursor, forum['id'], topic['id'], reply) 
     
    263280        req.hdf['discussion.message'] = message 
    264281        req.hdf['discussion.mode'] = mode 
     282        req.hdf['discussion.is_moderator'] = is_moderator 
    265283        db.commit() 
    266284        return mode + '.cs', None 
     
    269287    def get_message(self, cursor, id, req): 
    270288        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)
    273291        for row in cursor: 
    274292            row = dict(zip(columns, row)) 
     
    281299        columns = ('id', 'forum', 'time', 'subject', 'body', 'author') 
    282300        cursor.execute('SELECT id, forum, time, subject, body, author FROM' 
    283           ' topic WHERE id=%s', [id]
     301          ' topic WHERE id = %s' % (id)
    284302        for row in cursor: 
    285303            row = dict(zip(columns, row)) 
     
    292310        columns = ('name', 'moderators', 'id', 'time', 'subject', 'description') 
    293311        cursor.execute('SELECT name, moderators, id, time, subject, description' 
    294           ' FROM forum WHERE id = %s', [id]
     312          ' FROM forum WHERE id = %s' % (id)
    295313        for row in cursor: 
    296314            row = dict(zip(columns, row)) 
     
    302320    def get_forums(self, cursor, req): 
    303321        columns = ('moderators', 'id', 'time', 'subject', 'name', 
    304           'description', 'topics', 'replies', 'lastreply'
     322          'description', 'topics', 'replies', 'lastreply', 'lasttopic'
    305323        cursor.execute('SELECT moderators, id, time, subject, name,' 
    306324          ' description, (SELECT COUNT(id) FROM topic t WHERE' 
    307325          ' t.forum = forum.id), (SELECT COUNT(id) FROM message m WHERE m.forum' 
    308326          ' = 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') 
    310329        forums = [] 
    311330        for row in cursor: 
     
    317336            else: 
    318337                row['lastreply'] = 'No replies' 
     338            if row['lasttopic']: 
     339                row['lasttopic'] = pretty_timedelta(row['lasttopic']) 
     340            else: 
     341                row['lasttopic'] = 'No topics' 
    319342            row['time'] = format_datetime(row['time']) 
    320343            forums.append(row) 
     
    327350          ' COUNT(id) FROM message m WHERE m.topic = topic.id), (SELECT' 
    328351          ' 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)
    330353        topics = [] 
    331354        for row in cursor: 
  • discussionplugin/0.9/tracdiscussion/htdocs/css/discussion.css

    r790 r804  
    66 
    77/* Forum list */ 
    8 .forum-list t
     8.forum-list tr > t
    99{ 
    1010  margin: 0em !important; 
     
    1313} 
    1414 
    15 .forum-list .subject, .forum-list .description 
     15.forum-list tr > td > a 
    1616{ 
    17   margin: 0.5em; 
    18 
    19  
    20 .forum-list .table 
    21 
    22   display: table; 
     17  display: block; 
    2318  height: 100%; 
    24   width: 100%; 
     19  padding: 0.5em; 
     20  margin: 0em; 
    2521  border: none; 
    2622} 
    2723 
    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 
    4226{ 
    4327  text-align: center; 
  • discussionplugin/0.9/tracdiscussion/templates/forum-list.cs

    r790 r804  
    11<?cs include "discussion-header.cs" ?> 
    22 
    3 <h1>Forum Index</h1> 
     3<h1>Forum List</h1> 
    44<table class="listing"> 
    55  <thead> 
     
    77      <th class="subject">Forum</th> 
    88      <th class="moderators">Moderators</th> 
     9      <th class="lasttopic">Last Topic</th> 
    910      <th class="lastreply">Last Reply</th> 
    1011      <th class="founded">Founded</th> 
     
    2324        </td> 
    2425        <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> 
    2933          </a> 
    3034        </td> 
    3135        <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> 
    3638          </a> 
    3739        </td> 
    3840        <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> 
    4343          </a> 
    4444        </td> 
    4545        <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> 
    5048          </a> 
    5149        </td> 
    5250        <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> 
    5753          </a> 
    5854        </td> 
  • discussionplugin/0.9/tracdiscussion/templates/message-list.cs

    r790 r804  
    33<?cs def:display_preview() ?> 
    44  <li class="preview"> 
     5    <a name="preview"></a> 
    56    <div class="body"> 
    67      <?cs var:discussion.body ?> 
     
    1213<?cs /def ?> 
    1314 
    14 <?cs def:display_form()?> 
     15<?cs def:display_form() ?> 
    1516  <li class="reply"> 
    1617    <fieldset> 
     18      <a name="reply"></a> 
    1719      <legend> 
    1820         Reply: 
    1921      </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"> 
    2123        <div class="field"> 
    2224          <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 ?> 
    2430        </div> 
    2531        <div class="field"> 
     
    4248  <?cs each:message = messages ?> 
    4349    <li> 
     50      <a name="<?cs var:message.id ?>"></a> 
    4451      <div class="body"> 
    4552        <?cs var:message.body ?> 
    4653      </div> 
    4754      <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 ?> 
    5057          <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> 
    5158        <?cs /if ?> 
     
    6976<?cs /def ?> 
    7077 
    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> 
    7480<div class="topic"> 
    7581  <div class="header"> 
     
    8187    </div> 
    8288    <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> 
    8490    </div> 
    8591    <div class="author"> 
     
    102108</div> 
    103109 
    104 <?cs if:trac.acl.DISCUSSION_MODERATE ?> 
     110<?cs if:trac.acl.DISCUSSION_MODERATE && discussion.is_moderator ?> 
    105111  <div class="buttons"> 
    106112    <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  
    2828    <div class="field"> 
    2929      <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 ?> 
    3135    </div> 
    3236    <div class="field"> 
  • discussionplugin/0.9/tracdiscussion/templates/topic-list.cs

    r790 r804  
    11<?cs include "discussion-header.cs" ?> 
    22 
    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> 
    95  <table class="listing"> 
    106    <thead> 
  • discussionplugin/0.9/tracdiscussion/wiki.py

    r72 r804  
    33 
    44class DiscussionWiki(Component): 
     5    """ 
     6        The wiki module implements macros for forums, topics and messages 
     7        referencing. 
     8    """ 
    59    implements(IWikiSyntaxProvider) 
    610 
     
    1620    # Core code 
    1721    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 
    2524        db = self.env.get_db_cnx() 
    2625        cursor = db.cursor() 
    2726        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) 
    3535        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)) 
    3941                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) 
    4147        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)