Ticket #1749: ticketdelete-trac0.11-v3.patch

File ticketdelete-trac0.11-v3.patch, 12.6 kB (added by hkaimio, 1 year ago)

new version, tested with trac 0.11 r6202

  • ticketdelete/web_ui.py

    old new  
    55from trac.core import * 
    66from trac.web.api import IRequestFilter 
    77from trac.web.chrome import ITemplateProvider, add_script, add_stylesheet 
    8 from webadmin.web_ui import IAdminPageProvider 
     8from trac.admin.api import IAdminPanelProvider 
    99import re, traceback, pprint 
    1010from time import strftime, localtime 
     11from trac.ticket.model import Ticket 
    1112 
    1213__all__ = ['TicketDeletePlugin'] 
    1314 
    1415class TicketDeletePlugin(Component): 
    1516    """A small ticket deletion plugin.""" 
    1617     
    17     implements(ITemplateProvider, IAdminPageProvider, IRequestFilter) 
     18    implements(ITemplateProvider, IAdminPanelProvider, IRequestFilter) 
    1819 
    1920    # IRequestFilter methods 
    2021    def pre_process_request(self, req, handler): 
     
    2728            add_stylesheet(req, 'ticketdelete/ticketdelete.css') 
    2829        return template, content_type 
    2930  
    30     # IAdminPageProvider methods 
    31     def get_admin_pages(self, req): 
     31    # IAdminPanelProvider methods 
     32    def get_admin_panels(self, req): 
    3233        if req.perm.has_permission('TICKET_ADMIN'): 
    3334            yield ('ticket', 'Ticket System', 'delete', 'Delete') 
    3435            yield ('ticket', 'Ticket System', 'comments', 'Delete Changes') 
    3536             
    36     def process_admin_request(self, req, cat, page, path_info): 
     37    def render_admin_panel(self, req, cat, page, path_info): 
    3738        req.perm.assert_permission('TICKET_ADMIN') 
    3839         
    3940        data = {} 
     41        ticketdelete = {} 
    4042 
    41         data['ticketdelete.href'] = req.href('admin', cat, page) 
    42         data['ticketdelete.page'] = page 
    43         data['ticketdelete.redir'] = 1 
     43        ticketdelete['href'] = req.href('admin', cat, page) 
     44        ticketdelete['page'] = page 
     45        ticketdelete['redir'] = 1 
     46        data['ticketdelete'] = ticketdelete 
    4447 
    4548        if req.method == 'POST': 
    4649            if page == 'delete': 
    4750                if 'ticketid' in req.args and 'ticketid2' in req.args: 
    4851                    if req.args.get('ticketid') == req.args.get('ticketid2'): 
    49                         t = self._validate(req, req.args.get('ticketid')
     52                        t, ticketdelete = self._validate(req, req.args.get('ticketid'), ticketdelete
    5053                        if t: 
    5154                            self._delete_ticket(t.id) 
    52                             data['ticketdelete.message'] = "Ticket #%s has been deleted." % t.id 
     55                            ticketdelete['message'] = "Ticket #%s has been deleted." % t.id 
    5356                             
    5457                    else: 
    55                         data['ticketdelete.message'] = "The two IDs did not match. Please try again." 
     58                        ticketdelete['message'] = "The two IDs did not match. Please try again." 
    5659            elif page == 'comments': 
    5760                if 'ticketid' in req.args: 
    5861                    req.redirect(req.href.admin(cat, page, req.args.get('ticketid'))) 
    5962                else: 
    60                     t = self._validate(req, path_info
     63                    t, ticketdelete = self._validate(req, path_info, ticketdelete
    6164                    if t: 
    62                         data['ticketdelete.href'] = req.href('admin', cat, page, path_info) 
     65                        ticketdelete['href'] = req.href('admin', cat, page, path_info) 
    6366                        try: 
    6467                            deletions = None 
    6568                            if "multidelete" in req.args: 
     
    7477                                    ts = int(ts) 
    7578                                    self.log.debug('TicketDelete: Deleting change to ticket %s at %s (%s)'%(t.id,ts,field)) 
    7679                                    self._delete_change(t.id, ts, field) 
    77                                     data['ticketdelete.message'] = "Change to ticket #%s at %s has been modified" % (t.id, strftime('%a, %d %b %Y %H:%M:%S',localtime(ts))) 
    78                                     data['ticketdelete.redir'] = 0 
     80                                    ticketdelete['message'] = "Change to ticket #%s at %s has been modified" % (t.id, strftime('%a, %d %b %Y %H:%M:%S',localtime(ts))) 
     81                                    ticketdelete['redir'] = 0 
    7982                        except ValueError, e: 
    8083                            self.log.debug("TicketDelete: Error is %s"%e) 
    8184                            self.log.debug("TicketDelete: args = '%s'"%req.args.items()) 
    82                             data['ticketdelete.message'] = "Timestamp '%s' not valid" % req.args.get('ts')                     
     85                            ticketdelete['message'] = "Timestamp '%s' not valid" % req.args.get('ts')                     
    8386                     
    8487                 
    8588        if path_info: 
    86             t = self._validate(req, path_info
     89            t, ticketdelete = self._validate(req, path_info, ticketdelete
    8790            if t: 
    8891                if page == 'comments': 
    8992                    try: 
     
    9699                        data = ticket_data.setdefault(str(time), {}) 
    97100                        data.setdefault('fields', {})[field] = {'old': oldvalue, 'new': newvalue} 
    98101                        data['author'] = author 
    99                         data['prettytime'] = strftime('%a, %d %b %Y %H:%M:%S',localtime(time)) 
     102                        #data['prettytime'] = strftime('%a, %d %b %Y %H:%M:%S',localtime(0.10)) 
    100103                     
    101104                    # Remove all attachment changes                     
    102105                    for k, v in ticket_data.items(): 
     
    107110                    time_list = list(sorted(ticket_data.iterkeys())) 
    108111                    if selected is not None and selected < len(time_list): 
    109112                        ticket_data[time_list[selected]]['checked'] = True 
    110                     data['ticketdelete.changes'] = ticket_data 
     113                    ticketdelete['changes'] = [] 
     114                    for time in time_list: 
     115                        ticketdelete['changes'].append(ticket_data[time]) 
    111116                elif page == 'delete': 
    112                     data['ticketdelete.id'] = t.id 
     117                    ticketdelete['id'] = t.id 
    113118  
    114         return 'ticketdelete_admin.html', data, None 
     119        return 'ticketdelete_admin.html', data 
    115120 
    116121    # ITemplateProvider methods 
    117122    def get_templates_dirs(self): 
     
    145150        else: 
    146151            return (0,0) 
    147152 
    148     def _validate(self, req, arg): 
     153    def _validate(self, req, arg, ticketdelete): 
    149154        """Validate that arg is a string containing a valid ticket ID.""" 
    150155        try: 
    151156            id = int(arg) 
    152157            t = Ticket(self.env, id) 
    153             return t 
     158            return t, ticketdelete 
    154159        except TracError: 
    155             data['ticketdelete.message'] = "Ticket #%s not found. Please try again." % id 
     160            ticketdelete['message'] = "Ticket #%s not found. Please try again." % id 
    156161        except ValueError: 
    157             data['ticketdelete.message'] = "Ticket ID '%s' is not valid. Please try again." % arg 
    158         return False 
     162            ticketdelete['message'] = "Ticket ID '%s' is not valid. Please try again." % arg 
     163        return False, ticketdelete 
    159164                                                                                                                 
    160165     
    161166    def _delete_ticket(self, id): 
  • ticketdelete/htdocs/ticketdelete.js

    old new  
    77    } else { 
    88        $('#ticket table.properties').after('<div class="description"><h3><span class="inlinebuttons">'+delete_link+'</span>&nbsp;</h3></div>'); 
    99    } 
    10     $('#changelog h3').each(function() { 
     10    $('#changelog form').each(function() { 
     11        if (!/#comment$/.test(this.action)) { 
     12            return; 
     13        } 
    1114        var comment = $('input[@name=replyto]', this)[0]; 
    1215        if (comment) { 
    1316            comment = comment.value; 
  • ticketdelete/templates/ticketdelete_admin.html

    old new  
    1 <div xmlns="http://www.w3.org/1999/xhtml" 
    2   xmlns:py="http://genshi.edgewall.org/" 
    3   id="page"> 
    4   <h2>Delete Ticket<py:if ticketdelete.page="comments"> Changes</py:if></h2> 
     1<!DOCTYPE html 
     2    PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" 
     3    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> 
     4<html xmlns="http://www.w3.org/1999/xhtml" 
     5      xmlns:xi="http://www.w3.org/2001/XInclude" 
     6      xmlns:py="http://genshi.edgewall.org/"> 
     7  <xi:include href="admin.html" /> 
     8  <head> 
     9    <title>Delete</title> 
     10  </head> 
     11<body> 
    512 
     13  <h2>Delete Ticket<py:if test="ticketdelete.page == 'comments'"> Changes</py:if></h2> 
     14 
    615  <py:choose> 
    716    <py:when test="ticketdelete.message and ticketdelete.redir"> 
    817      <b>${ticketdelete.message}</b><br /> 
     
    2231      </form> 
    2332    </py:when> 
    2433    <py:when test="ticketdelete.page == 'comments'"> 
    25       <py:choose has_tickets="len(ticketdelete.changes)"> 
    26         <py:when has_tickets="True"> 
     34      <py:choose test="len(ticketdelete.changes)"> 
     35        <py:when test="True"> 
    2736          <py:if test="ticketdelete.message"> 
    2837            <p><b>${ticketdelete.message}</b></p> 
    2938          </py:if> 
     
    3443            <tbody> 
    3544              <py:for each="change in ticketdelete.changes"> 
    3645                <tr> 
    37                   <td><input type="checkbox" name="dontcare" value="dontcare" id="checkbox_${change}" checked="${change.checked or None}" /></td> 
     46                  <td><input type="checkbox" name="dontcare" value="dontcare" id="checkbox_${change}" checked="${change.checked or None}" onchange="syncchecks(this)" /></td> 
    3847                  <td colspan="3"><b>Change at ${change.prettytime} by ${change.author}</b></td> 
    3948                  <td><input type="submit" name="delete_${change}" value="Delete change" /></td> 
    4049                  <tr> 
    4150                    <py:for each="field in change.fields"> 
    4251                      <tr> 
    43                         <td><input type="checkbox" id="checkbox${field}_${change}" name="mdelete" value="${field}_${change}" checked="${change.checked or None}" /></td> 
     52                        <td><input type="checkbox" id="checkbox_${change}_${field}" name="mdelete" value="${field}_${change}" checked="${change.checked or None}" onchange="if(this.checked) { $('#checkbox_${change}').checked = 0; }" /></td> 
     53 
    4454                        <td>${field}</td> 
    45                         <py:choose test="name(field)"> 
     55                        <py:choose test="str(field)"> 
    4656                          <td py:when="comment" colspan="2">${field.new}</td> 
    4757 
    4858                          <py:otherwise> 
     
    6171         
    6272        <script type="text/javascript"> 
    6373        <!-- 
    64             function toggleboxen(me, boxen)  
     74            function syncchecks(me)  
    6575            { 
    66                 status = document.getElementById("checkbox_" + me).checked; 
    67                 boxen.pop() // Remove the last (blank) entry. 
    68                 for (box in boxen) { 
    69                     //alert("Changing checkbox"+boxen[box]+"_"+me); 
    70                     document.getElementById("checkbox"+boxen[box]+"_"+me).checked = status; 
     76                var checked = me.checked; 
     77                var checks = document.getElementsByTagName("input"); 
     78                var re = new RegExp("^" + me.id + "_"); 
     79                for (var i = 0, l = checks.length; i < l; i ++) { 
     80                    var check = checks[i]; 
     81                    if (check.type == "checkbox" && re.test(check.id)) { 
     82                      check.checked = checked; 
     83                    } 
    7184                } 
    7285            } 
    73              
    74             <py:for each="change in ticketdelete.changes"> 
    75             addEvent(document.getElementById("checkbox_${change}"), "change", function() { 
    76                 var boxen = Array(${py:for each="field in change.fields"${field}",</py:for>""); 
    77                 toggleboxen("${change}", boxen); //Array(<py:for each="field in change.fields">"${field}",</py:for>)); 
    78             }); 
    79             <py:for each="field in change.fields"> 
    80               addEvent(document.getElementById("checkbox${field}_${change}"),"change", function() { 
    81                   if(!document.getElementById("checkbox${field}_${change}").checked) { 
    82                   document.getElementById("checkbox${change}").checked = 0; 
    83                 } 
    84             }); 
    85             </py:for> 
    86             </py:for> 
    87  
    88  
    8986        //--> 
    9087        </script> 
    9188 
     
    104101      </py:choose> 
    105102    </py:when> 
    106103  </py:choose> 
    107 </div> 
     104</body> 
     105 
     106</html>