Edgewall Software

Ticket #2141: miltiFileAttach.r7578.patch

File miltiFileAttach.r7578.patch, 7.8 KB (added by vnaum@…, 6 weeks ago)

Slava Zanko's multifile attachment patch, updated to r7578

  • trac/attachment.py

     
    541541 
    542542    # Internal methods 
    543543 
    544     def _do_save(self, req, attachment): 
     544    def _do_save_one(self, req, attachment, upload, description): 
    545545        req.perm(attachment.resource).require('ATTACHMENT_CREATE') 
    546546 
    547         if 'cancel' in req.args: 
    548             req.redirect(get_resource_url(self.env, attachment.resource.parent, 
    549                                           req.href)) 
    550547 
    551         upload = req.args['attachment'] 
    552548        if not hasattr(upload, 'filename') or not upload.filename: 
    553549            raise TracError(_('No file uploaded')) 
    554550        if hasattr(upload.file, 'fileno'): 
     
    576572            raise TracError(_('No file uploaded')) 
    577573        # Now the filename is known, update the attachment resource 
    578574        # attachment.filename = filename 
    579         attachment.description = req.args.get('description', '') 
     575        attachment.description = description 
    580576        attachment.author = get_reporter_id(req, 'author') 
    581577        attachment.ipnr = req.remote_addr 
    582578 
     
    605601            attachment.filename = None 
    606602        attachment.insert(filename, upload.file, size) 
    607603 
    608         req.redirect(get_resource_url(self.env, attachment.resource(id=None), 
     604    def _do_save_many(self,req, attachment): 
     605        curr_attach = 0 
     606        while curr_attach < int(req.args['multiple_attachments']): 
     607            upload=req.args['attachment-%d' % curr_attach] 
     608            if hasattr(upload, 'filename') and upload.filename: 
     609                attachment.filename = None 
     610                self._do_save_one(req, attachment, upload, req.args.get('description-%d' % curr_attach, '')) 
     611            curr_attach=curr_attach+1 
     612 
     613    def _do_save(self, req, attachment): 
     614        req.perm(attachment.resource).require('ATTACHMENT_CREATE') 
     615 
     616        if 'cancel' in req.args: 
     617            req.redirect(get_resource_url(self.env, attachment.resource.parent, 
     618                                          req.href)) 
     619 
     620        if 'multiple_attachments' in req.args: 
     621            self._do_save_many(req, attachment) 
     622            req.redirect(get_resource_url(self.env, attachment.resource(id=None), 
    609623                                      req.href)) 
     624        else: 
     625            self._do_save_one(req, attachment, req.args['attachment'], req.args.get('description', '')) 
     626            # Redirect the user to list of attachments (must add a trailing '/') 
     627            req.redirect(get_resource_url(self.env, attachment.resource(id=None), 
     628                                      req.href)) 
    610629 
    611630    def _do_delete(self, req, attachment): 
    612631        req.perm(attachment.resource).require('ATTACHMENT_DELETE') 
  • trac/htdocs/js/trac.js

     
    7171  window.getAncestorByTagName = function(elem, tagName) { 
    7272    return $(elem).parents(tagName).get(0); 
    7373  } 
     74})(jQuery); 
    7475 
    75 })(jQuery); 
    76  No newline at end of file 
     76var ATTACHFILE_COUNTER=0; 
     77function manageMultipleAttachFields(_obj){ 
     78    if (_obj.value == '') { 
     79        if($("#multiAttach_tbody").get(0).rows.length == 1) return; 
     80      $("#multiAttach_tbody").get(0).deleteRow($(_obj).attr("attachnum")*1); 
     81      ATTACHFILE_COUNTER=0; 
     82      $("#multiAttach_tbody tr").each(function(index, element){ 
     83          $("input", $("td", element).get(0)) 
     84              .attr("attachnum",ATTACHFILE_COUNTER) 
     85              .get(0).name = "attachment-"+ATTACHFILE_COUNTER; 
     86          $("input", $("td", element).get(1)) 
     87              .get(0).name = "description-"+ATTACHFILE_COUNTER; 
     88          ATTACHFILE_COUNTER++; 
     89      }); 
     90      $("#multiAttach_count").get(0).value = $("#multiAttach_count").val()*1-1; 
     91    } else { 
     92      if ($(_obj).attr("attachnum") != $("#multiAttach_count").val()-1) return; 
     93      var tr = $("#multiAttach_tbody").get(0).insertRow(-1); 
     94      var td = tr.insertCell(-1); 
     95      $('<input type="file" onchange="manageMultipleAttachFields(this)">') 
     96         .attr("attachnum",$("#multiAttach_count").val()) 
     97         .appendTo(td) 
     98         .get(0).name = "attachment-"+$("#multiAttach_count").val(); 
     99 
     100      td = tr.insertCell(-1); 
     101      $('<input type="text">') 
     102          .attr("size",60) 
     103          .appendTo(td) 
     104          .get(0).name = "description-"+$("#multiAttach_count").val(); 
     105      $("#multiAttach_count").get(0).value = $("#multiAttach_count").val()*1+1; 
     106    } 
     107} 
     108 
  • trac/templates/attachment.html

     
    1212 
    1313  <body py:with="parent = attachments and attachments.parent or 
    1414                          attachment.resource.parent"> 
    15     <div py:choose="mode" id="content" class="attachment"> 
    16       <py:when test="'new'"> 
    17         <h1>Add Attachment to <a href="${url_of(parent)}">${name_of(parent)}</a></h1> 
    18         <form id="attachment" method="post" enctype="multipart/form-data" action=""> 
     15    <py:def function="attach_oneFile()"> 
     16      <div class="field"> 
     17        <label>File:<br /><input type="file" name="attachment" /></label> 
     18      </div> 
     19      <fieldset> 
     20        <legend>Attachment Info</legend> 
     21        <py:if test="authname == 'anonymous'"> 
    1922          <div class="field"> 
    20             <label>File<py:if test="max_size >= 0"> (size limit 
    21                   ${pretty_size(max_size, format='%d')})</py:if>:<br /> 
    22               <input type="file" name="attachment" /></label> 
     23            <label>Your email or username:<br /> 
     24              <input type="text" name="author" size="30" value="$author" /> 
     25            </label> 
    2326          </div> 
     27          </py:if> 
     28        <div class="field"> 
     29          <label>Description of the file (optional):<br /> 
     30            <input type="text" name="description" size="60" /></label> 
     31        </div> 
     32        <br /> 
     33        <div class="options"> 
     34          <label><input type="checkbox" name="replace" /> 
     35            Replace existing attachment of the same name</label> 
     36        </div> 
     37        <br /> 
     38      </fieldset> 
     39    </py:def> 
     40    <py:def function="attach_multiFile()"> 
     41         <table><thead> 
     42          <tr><th align="left">File</th><th align="left">Description</th></tr> 
     43         </thead> 
     44        <tbody id="multiAttach_tbody"> 
     45        <tr> 
     46            <td><input type="file" attachnum="0" name="attachment-0" onchange="manageMultipleAttachFields(this);"/></td> 
     47            <td><input type="text" name="description-0" size="60" /></td> 
     48        </tr> 
     49        </tbody></table> 
     50        <input type="hidden" id="multiAttach_count" name="multiple_attachments" value="1" /> 
     51 
    2452          <fieldset> 
    2553            <legend>Attachment Info</legend> 
    2654            <py:if test="authname == 'anonymous'"> 
     
    3058                </label> 
    3159              </div> 
    3260              </py:if> 
    33             <div class="field"> 
    34               <label>Description of the file (optional):<br /> 
    35                 <input type="text" name="description" size="60" /></label> 
    36             </div> 
    37             <br /> 
    3861            <div class="options"> 
    3962              <label><input type="checkbox" name="replace" /> 
    40                 Replace existing attachment of the same name</label> 
     63                Replace existing attachments of the same name</label> 
    4164            </div> 
    4265            <br /> 
    4366          </fieldset> 
     67    </py:def> 
     68 
     69    <div py:choose="mode" id="content" class="attachment"> 
     70      <py:when test="'new'"> 
     71        <h1>Add Attachment to <a href="${url_of(parent)}">${name_of(parent)}</a></h1> 
     72        <form id="attachment" method="post" enctype="multipart/form-data" action=""> 
     73         
     74        ${attach_multiFile()} 
    4475          <div class="buttons"> 
    4576            <input type="hidden" name="action" value="new" /> 
    4677            <input type="hidden" name="realm" value="$parent.realm" />