Changeset 530

Show
Ignore:
Timestamp:
03/21/06 21:32:51 (3 years ago)
Author:
coderanger
Message:

TicketDeletePlugin:

Now allows for deleting individual changes, both whole changes and comments.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • ticketdeleteplugin/0.9/ticketdelete/templates/ticketdelete_admin.cs

    r501 r530  
    1 <h2>Delete Ticket</h2> 
     1<h2>Delete Ticket<?cs if:ticketdelete.page=='comments' ?> Changes<?cs /if ?></h2> 
    22 
    33<?cs if:ticketdelete.message ?> 
    4 <b><?cs var:ticketdelete.message ?></b><br /> 
    5 <a href="<?cs var:ticketdelete.href ?>">Back</a> 
    6 <?cs else ?> 
    7 <p> 
    8 <b>Note: This is intended only for use in very odd circumstances.<br /> 
    9 It is usually a better idea to resolve a ticket as invalid, than to remove it from the database.</b> 
    10 </p> 
     4    <b><?cs var:ticketdelete.message ?></b><br /> 
     5    <a href="<?cs var:ticketdelete.href ?>">Back</a> 
     6<?cs elif:ticketdelete.page == 'delete' ?> 
     7    <p> 
     8        <b>Note: This is intended only for use in very odd circumstances.<br /> 
     9        It is usually a better idea to resolve a ticket as invalid, than to remove it from the database.</b> 
     10    </p> 
    1111 
    12 <form method="post" onsubmit="return confirm('Are you sure you want to do this?')"> 
    13 Ticket ID: <input type="text" name="ticketid" /><br /> 
    14 Again: <input type="text" name="ticketid2" /><br /> 
    15 <input type="submit" value="Delete" /> 
    16 </form> 
     12    <form method="post" onsubmit="return confirm('Are you sure you want to do this?')"> 
     13        Ticket ID: <input type="text" name="ticketid" /><br /> 
     14        Again: <input type="text" name="ticketid2" /><br /> 
     15        <input type="submit" value="Delete" /> 
     16    </form> 
     17<?cs elif:ticketdelete.page == 'comments' ?> 
     18    <?cs if:len(ticketdelete.changes) ?> 
     19        <p>Please selet a change to delete</p> 
     20        <?cs each:change = ticketdelete.changes ?> 
     21            <div> 
     22                <b><?cs var:change.prettytime ?></b><br /> 
     23                Change by <?cs var:change.author ?><br /> 
     24                <?cs each:field = change.fields ?> 
     25                    <?cs if:name(field)=='comment' ?> 
     26                        Comment: <?cs var:field.new ?><br /> 
     27                    <?cs else ?> 
     28                        <?cs name:field ?>: From '<?cs var:field.old ?>' to '<?cs var:field.new ?>'<br /> 
     29                    <?cs /if ?> 
     30                <?cs /each ?> 
     31                <form method="post"> 
     32                    <input type="hidden" name="ts" value="<?cs name:change ?>" /> 
     33                    <input type="submit" name="delete_all" value="Delete Entire Change" /> 
     34                    <input type="submit" name="delete_only" value="Delete Comment Only" /> 
     35                </form> 
     36            </div><br /> 
     37        <?cs /each ?> 
     38        <br /> 
     39        <a href="<?cs var:ticketdelete.href ?>">Back</a> 
     40    <?cs else ?> 
     41        <form method="post"> 
     42            <p>Select a ticket ID to change.</p> 
     43            <p> 
     44                Ticket ID: <input type="text" name="ticketid" /><br /> 
     45                <input type="submit" value="Submit" /> 
     46            </p> 
     47        </form> 
     48    <?cs /if ?> 
    1749<?cs /if ?> 
  • ticketdeleteplugin/0.9/ticketdelete/web_ui.py

    r501 r530  
    55from trac.ticket.model import Ticket 
    66from trac.web.chrome import ITemplateProvider 
     7import pkg_resources 
     8pkg_resources.require('TracWebAdmin') 
    79from webadmin.web_ui import IAdminPageProvider 
    8 import re 
     10import re, traceback 
     11from time import strftime, localtime 
    912 
    1013__all__ = ['TicketDeletePlugin'] 
     
    1922        if req.perm.has_permission('TICKET_ADMIN'): 
    2023            yield ('ticket', 'Ticket System', 'delete', 'Delete') 
     24            yield ('ticket', 'Ticket System', 'comments', 'Delete Changes') 
    2125             
    2226    def process_admin_request(self, req, cat, page, path_info): 
    2327        assert req.perm.has_permission('TICKET_ADMIN') 
    2428         
     29        req.hdf['ticketdelete.href'] = self.env.href('admin', cat, page) 
     30        req.hdf['ticketdelete.page'] = page 
     31 
    2532        if req.method == 'POST': 
    26             if 'ticketid' in req.args and 'ticketid2' in req.args: 
    27                 if req.args.get('ticketid') == req.args.get('ticketid2'): 
    28                     try: 
    29                         id = int(req.args.get('ticketid')) 
    30                         t = Ticket(self.env, id) 
    31                         self._delete_ticket(id) 
    32                         req.hdf['ticketdelete.message'] = "Ticket #%s has been deleted." % id 
    33                     except TracError: 
    34                         req.hdf['ticketdelete.message'] = "Ticket #%s not found. Please try again." % id 
    35                     except ValueError: 
    36                         req.hdf['ticketdelete.message'] = "Ticket ID '%s' is not valid. Please try again." % req.args.get('ticketid') 
    37                 else: 
    38                     req.hdf['ticketdelete.message'] = "The two IDs did not match. Please try again." 
    39         req.hdf['ticketdelete.href'] = self.env.href('admin','ticket','delete') 
     33            if page == 'delete': 
     34                if 'ticketid' in req.args and 'ticketid2' in req.args: 
     35                    if req.args.get('ticketid') == req.args.get('ticketid2'): 
     36                        t = self._validate(req, req.args.get('ticketid')) 
     37                        if t: 
     38                            self._delete_ticket(t.id) 
     39                            req.hdf['ticketdelete.message'] = "Ticket #%s has been deleted." % id 
     40                             
     41                    else: 
     42                        req.hdf['ticketdelete.message'] = "The two IDs did not match. Please try again." 
     43            elif page == 'comments': 
     44                if 'ticketid' in req.args: 
     45                    req.redirect(self.env.href.admin(cat, page, req.args.get('ticketid'))) 
     46                if 'ts' in req.args: 
     47                    t = self._validate(req, path_info) 
     48                    if t: 
     49                        req.hdf['ticketdelete.href'] = self.env.href('admin', cat, page, path_info) 
     50                        try: 
     51                            ts = int(req.args.get('ts')) 
     52                            self._delete_change(t.id, ts, 'delete_only' in req.args) 
     53                            req.hdf['ticketdelete.message'] = "Change to ticket #%s at %s has been modified" % (t.id, strftime('%a, %d %b %Y %H:%M:%S',localtime(ts))) 
     54                        except ValueError: 
     55                            req.hdf['ticketdelete.message'] = "Timestamp '%s' not valid" % req.args.get('ts') 
     56                            self.log.debug(traceback.format_exc()) 
     57                     
     58                     
     59                 
     60        if page == 'comments': 
     61            if path_info: 
     62                t = self._validate(req, path_info) 
     63                if t: 
     64                    for time, author, field, oldvalue, newvalue in t.get_changelog(): 
     65                        req.hdf['ticketdelete.changes.%s.fields.%s'%(time,field)] = {'old': oldvalue, 'new': newvalue} 
     66                        req.hdf['ticketdelete.changes.%s.author'%time] = author 
     67                        req.hdf['ticketdelete.changes.%s.prettytime'%time] = strftime('%a, %d %b %Y %H:%M:%S',localtime(time)) 
     68                     
     69                 
    4070        return 'ticketdelete_admin.cs', None 
    4171 
     
    6696 
    6797    # Internal methods 
     98    def _get_trac_version(self): 
     99        md = re.match('(\d+)\.(\d+)',TRAC_VERSION) 
     100        if md: 
     101            return (int(md.group(1)),int(md.group(2))) 
     102        else: 
     103            return (0,0) 
     104 
     105    def _validate(self, req, arg): 
     106        """Validate that arg is a string containing a valid ticket ID.""" 
     107        try: 
     108            id = int(arg) 
     109            t = Ticket(self.env, id) 
     110            return t 
     111        except TracError: 
     112            req.hdf['ticketdelete.message'] = "Ticket #%s not found. Please try again." % id 
     113        except ValueError: 
     114            req.hdf['ticketdelete.message'] = "Ticket ID '%s' is not valid. Please try again." % arg 
     115        return False 
     116                                                                                                                 
     117     
    68118    def _delete_ticket(self, id): 
    69         md = re.match('(\d+)\.(\d+)',TRAC_VERSION) 
    70         if md and (int(md.group(2)) >= 10 or int(md.group(1)) > 0): 
     119        """Delete the given ticket ID.""" 
     120        major, minor = self._get_trac_version() 
     121        if major > 0 or minor >= 10: 
    71122            ticket = Ticket(self.env,id) 
    72123            ticket.delete() 
     
    79130            cursor.execute("DELETE FROM ticket_custom WHERE ticket=%s", (id,)) 
    80131            db.commit() 
     132             
     133    def _delete_change(self, ticket, ts, just_comment=False): 
     134        """Delete the change on the given ticket at the given timestamp.""" 
     135        db = self.env.get_db_cnx() 
     136        cursor = db.cursor() 
     137        if just_comment: 
     138            cursor.execute("DELETE FROM ticket_change WHERE ticket = %s AND time = %s AND field = 'comment'", (ticket, ts)) 
     139        else: 
     140            cursor.execute('DELETE FROM ticket_change WHERE ticket = %s AND time = %s', (ticket, ts)) 
     141        db.commit()