Changeset 771


Ignore:
Timestamp:
12/18/08 12:04:04 (4 years ago)
Author:
cbalan
Message:

CustomFieldAdminPlugin?: - Sync with  th:changeset:4964

Location:
trunk/trac-hacks/customfieldadminplugin/customfieldadmin
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/trac-hacks/customfieldadminplugin/customfieldadmin/api.py

    r56 r771  
    66License: BSD 
    77 
    8 (c) 2005-2007 ::: www.CodeResort.com - BV Network AS (simon-code@bvnetwork.no) 
     8(c) 2005-2008 ::: www.CodeResort.com - BV Network AS (simon-code@bvnetwork.no) 
    99""" 
     10 
     11import re 
    1012 
    1113from trac.core import * 
    1214from trac.ticket.model import TicketSystem 
    13 import re 
     15from trac.util.text import to_unicode 
    1416 
    1517__all__ = ['CustomFields'] 
     
    2022    (The get_custom_fields is already part of the API - just redirect here, 
    2123     and add option to only get one named field back.) 
     24     
     25    Input to methods is a 'customfield' dict supporting these keys: 
     26        name = name of field (alphanumeric only) 
     27        type = text|checkbox|select|radio|textarea 
     28        label = label description 
     29        value = default value for field content 
     30        options = options for select and radio types (list, leave first empty for optional) 
     31        cols = number of columns for text area 
     32        rows = number of rows for text area 
     33        order = specify sort order for field 
    2234    """ 
    2335     
     
    3446                    return item 
    3547            return None        # item not found 
    36          
    37     def update_custom_field(self, env, customfield, create=False): 
    38         """ Update or create a new custom field (if requested). 
    39         customfield is a dictionary with the following possible keys: 
    40             name = name of field (alphanumeric only) 
    41             type = text|checkbox|select|radio|textarea 
    42             label = label description 
    43             value = default value for field content 
    44             options = options for select and radio types (list, leave first empty for optional) 
    45             cols = number of columns for text area 
    46             rows = number of rows for text area 
    47             order = specify sort order for field 
    48         """ 
     48     
     49    def verify_custom_field(self, env, customfield, create=True): 
     50        """ Basic validation of the input for modifying or creating 
     51        custom fields. """ 
    4952        # Name, Type and Label is required 
    50         if not (customfield.has_key('name') and customfield.has_key('type') \ 
    51                 and customfield.has_key('label')): 
     53        if not (customfield.get('name') and customfield.get('type') \ 
     54                and customfield.get('label')): 
    5255            raise TracError("Custom field needs at least a name, type and label.") 
    5356        # Use lowercase custom fieldnames only 
    54         customfield['name'] = str(customfield['name']).lower() 
     57        customfield['name'] = to_unicode(customfield['name']).lower() 
    5558        # Only alphanumeric characters (and [-_]) allowed for custom fieldname 
    56         # Note: This is not pretty, but it works... Anyone have an eaier way of checking ??? 
    57         matchlen = re.search("[a-z0-9-_]+", customfield['name']).span() 
    58         namelen = len(customfield['name']) 
    59         if (matchlen[1]-matchlen[0] != namelen): 
    60             raise TracError("Only alphanumeric characters allowed for custom field name (a-z or 0-9 or -_).") 
    61         # If Create, check that field does not already exist 
    62         if create and env.config.get('ticket-custom', customfield['name']): 
    63             raise TracError("Can not create as field already exists.") 
     59        if re.search('^[a-z0-9-_]+$', customfield['name']) == None: 
     60           raise TracError("Only alphanumeric characters allowed for custom field name (a-z or 0-9 or -_).") 
    6461        # Check that it is a valid field type 
    6562        if not customfield['type'] in ['text', 'checkbox', 'select', 'radio', 'textarea']: 
    6663            raise TracError("%s is not a valid field type" % customfield['type']) 
    67         # Create/update the field name and type 
     64        # Check that field does not already exist (if modify it should already be deleted) 
     65        if create and env.config.get('ticket-custom', customfield['name']): 
     66            raise TracError("Can not create as field already exists.") 
     67     
     68    def create_custom_field(self, env, customfield): 
     69        """ Create the new custom fields (that may just have been deleted as part 
     70        of 'modify'). Note: Caller is responsible for verifying input before create.""" 
     71        # Set the mandatory items 
    6872        env.config.set('ticket-custom', customfield['name'], customfield['type']) 
    69         # Set the field label 
    7073        env.config.set('ticket-custom', customfield['name'] + '.label', customfield['label']) 
    71         # Set default value if it exist in dictionay with value, else remove it if it exists in config 
    72         if customfield.has_key('value') and customfield['value']: 
     74        # Optional items 
     75        if 'value' in customfield: 
    7376            env.config.set('ticket-custom', customfield['name'] + '.value', customfield['value']) 
    74         elif env.config.get('ticket-custom', customfield['name'] + '.value'): 
    75             env.config.remove('ticket-custom', customfield['name'] + '.value') 
    76         # If select or radio set options, or remove if it exists and field no longer need options 
    77         if customfield['type'] in ['select', 'radio']: 
    78             if not customfield.has_key('options') or customfield['options'] == []: 
    79                 raise TracError("No options specified for %s field" % customfield['type']) 
     77        if 'options' in customfield: 
    8078            env.config.set('ticket-custom', customfield['name'] + '.options', '|'.join(customfield['options'])) 
    81         elif env.config.get('ticket-custom', customfield['name'] + '.options'): 
    82             env.config.remove('ticket-custom', customfield['name'] + '.options') 
    83         # Set defaults for textarea if none is specified, remove settings if no longer used 
     79        # Textarea 
    8480        if customfield['type'] == 'textarea': 
    85             if (not customfield.has_key('cols')) or (not str(customfield['cols']).isdigit()): 
    86                 customfield['cols'] = "60" 
    87             if (not customfield.has_key('rows')) or (not str(customfield['rows']).isdigit()): 
    88                 customfield['rows'] = "5" 
    89             env.config.set('ticket-custom', customfield['name'] + '.cols', customfield['cols']) 
    90             env.config.set('ticket-custom', customfield['name'] + '.rows', customfield['rows']) 
    91         elif env.config.get('ticket-custom', customfield['name'] + '.cols'): 
    92             env.config.remove('ticket-custom', customfield['name'] + '.cols') 
    93         # Set sort setting if it is in customfield dict, remove if no longer present 
    94         if create: 
    95             last = len(self.get_custom_fields(env)) 
    96             env.config.set('ticket-custom', customfield['name'] + '.order', 
    97                     customfield.get('order',0) or last) 
    98         elif customfield.has_key('order') and customfield['order']: 
    99             # Exists and have value - note: will not update order conflicting with other fields 
    100             if str(customfield['order']).isdigit(): 
    101                 env.config.set('ticket-custom', customfield['name'] + '.order', customfield['order']) 
    102         elif env.config.get('ticket-custom', customfield['name'] + '.order'): 
    103             env.config.remove('ticket-custom', customfield['name'] + '.order') 
    104         # Save settings 
     81            cols = customfield.get('cols') and int(customfield.get('cols', 0)) > 0 \ 
     82                                                and customfield.get('cols') or 60 
     83            rows = customfield.get('rows', 0) and int(customfield.get('rows', 0)) > 0 \ 
     84                                                and customfield.get('rows') or 5 
     85            env.config.set('ticket-custom', customfield['name'] + '.cols', cols) 
     86            env.config.set('ticket-custom', customfield['name'] + '.rows', rows) 
     87        # Order 
     88        order = customfield.get('order', "") 
     89        if order == "": 
     90            order = len(self.get_custom_fields(env)) 
     91        env.config.set('ticket-custom', customfield['name'] + '.order', order) 
    10592        env.config.save() 
    10693 
    107     def delete_custom_field(self, env, customfield): 
     94    def update_custom_field(self, env, customfield, create=False): 
     95        """ Updates a custom. Option to 'create' is kept in order to keep 
     96        the API backwards compatible. """ 
     97        if create: 
     98            self.verify_custom_field(env, customfield) 
     99            self.create_custom_field(env, customfield) 
     100            return 
     101        # Check input, then delete and save new 
     102        self.verify_custom_field(env, customfield, create=False) 
     103        self.delete_custom_field(env, customfield, modify=True) 
     104        self.create_custom_field(env, customfield) 
     105     
     106    def delete_custom_field(self, env, customfield, modify=False): 
    108107        """ Deletes a custom field. 
    109108        Input is a dictionary (see update_custom_field), but only ['name'] is required. 
     
    111110        if not env.config.get('ticket-custom', customfield['name']): 
    112111            return # Nothing to do here - cannot find field 
    113         # Need to redo the order of fields that are after the field to be deleted 
    114         order_to_delete = env.config.getint('ticket-custom', customfield['name']+'.order') 
    115         cfs = self.get_custom_fields(env) 
    116         for field in cfs: 
    117             if field['order'] > order_to_delete: 
    118                 env.config.set('ticket-custom', field['name']+'.order', field['order'] -1 ) 
     112        if not modify: 
     113            # Permanent delete - reorder later fields to lower order 
     114            order_to_delete = env.config.getint('ticket-custom', customfield['name']+'.order') 
     115            cfs = self.get_custom_fields(env) 
     116            for field in cfs: 
     117                if field['order'] > order_to_delete: 
     118                    env.config.set('ticket-custom', field['name']+'.order', field['order'] -1 ) 
    119119        # Remove any data for the custom field (covering all bases) 
    120120        env.config.remove('ticket-custom', customfield['name']) 
     
    125125        env.config.remove('ticket-custom', customfield['name'] + '.rows') 
    126126        env.config.remove('ticket-custom', customfield['name'] + '.order') 
    127         # Save settings 
    128         env.config.save() 
     127        # Persist permanent deletes 
     128        if not modify: 
     129            env.config.save() 
  • trunk/trac-hacks/customfieldadminplugin/customfieldadmin/customfieldadmin.py

    r448 r771  
    55License: BSD 
    66 
    7 (c) 2005-2007 ::: www.CodeResort.com - BV Network AS (simon-code@bvnetwork.no) 
     7(c) 2005-2008 ::: www.CodeResort.com - BV Network AS (simon-code@bvnetwork.no) 
    88(c) 2007      ::: www.Optaros.com (.....) 
    99""" 
     
    3939                      'cols': to_unicode(req.args.get('cols')), 
    4040                      'rows': to_unicode(req.args.get('rows')), 
    41                       'order': req.args.get('order', 0)} 
     41                      'order': req.args.get('order', '')} 
    4242            return cfdict 
    4343         
     
    9090                                  if key.startswith('order_')]) 
    9191                    values = dict([(val, True) for val in order.values()]) 
    92                     if len(order) != len(values): 
    93                         raise TracError, 'Order numbers must be unique.' 
    9492                    cf = cfapi.get_custom_fields(self.env) 
    9593                    for cur_cf in cf: 
  • trunk/trac-hacks/customfieldadminplugin/customfieldadmin/templates/customfieldadmin.html

    r347 r771  
    139139              <td>${cf.label}</td> 
    140140              <td class="default"> 
    141                 <select name="order_${cf.name}"> 
    142                   <option py:for="other in cfadmin.customfields" 
    143                       selected="${other.order==cf.order and 'selected' or None}"> 
    144                       ${other.order} 
     141                <select name="order_${cf.name}" py:with="count = len(cfadmin.customfields)"> 
     142                  <option py:for="num in range(count)" 
     143                      selected="${num==cf.order and 'selected' or None}"> 
     144                      ${num} 
    145145                  </option> 
     146                  <!--! Extra option in case value is outside regular range --> 
     147                  <py:if test="cf.order not in range(count)"> 
     148                    <option disabled="disabled">&mdash;</option> 
     149                    <option selected="selected" 
     150                        title="Currently outside regular range">${cf.order}</option> 
     151                  </py:if> 
    146152                </select> 
    147153              </td> 
Note: See TracChangeset for help on using the changeset viewer.