Changeset 4964
- Timestamp:
- Dec 6, 2008, 1:06:59 AM (15 years ago)
- Location:
- customfieldadminplugin/0.11/customfieldadmin
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
customfieldadminplugin/0.11/customfieldadmin/api.py
r2250 r4964 6 6 License: BSD 7 7 8 (c) 2005-200 7::: www.CodeResort.com - BV Network AS (simon-code@bvnetwork.no)8 (c) 2005-2008 ::: www.CodeResort.com - BV Network AS (simon-code@bvnetwork.no) 9 9 """ 10 11 import re 10 12 11 13 from trac.core import * 12 14 from trac.ticket.model import TicketSystem 13 import re15 from trac.util.text import to_unicode 14 16 15 17 __all__ = ['CustomFields'] … … 20 22 (The get_custom_fields is already part of the API - just redirect here, 21 23 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 22 34 """ 23 35 … … 34 46 return item 35 47 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. """ 49 52 # 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')): 52 55 raise TracError("Custom field needs at least a name, type and label.") 53 56 # Use lowercase custom fieldnames only 54 customfield['name'] = str(customfield['name']).lower()57 customfield['name'] = to_unicode(customfield['name']).lower() 55 58 # 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 -_).") 64 61 # Check that it is a valid field type 65 62 if not customfield['type'] in ['text', 'checkbox', 'select', 'radio', 'textarea']: 66 63 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 68 72 env.config.set('ticket-custom', customfield['name'], customfield['type']) 69 # Set the field label70 73 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 config72 if customfield.has_key('value') and customfield['value']:74 # Optional items 75 if 'value' in customfield: 73 76 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: 80 78 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 84 80 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) 105 92 env.config.save() 106 93 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): 108 107 """ Deletes a custom field. 109 108 Input is a dictionary (see update_custom_field), but only ['name'] is required. … … 111 110 if not env.config.get('ticket-custom', customfield['name']): 112 111 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 ) 119 119 # Remove any data for the custom field (covering all bases) 120 120 env.config.remove('ticket-custom', customfield['name']) … … 125 125 env.config.remove('ticket-custom', customfield['name'] + '.rows') 126 126 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() -
customfieldadminplugin/0.11/customfieldadmin/customfieldadmin.py
r4016 r4964 5 5 License: BSD 6 6 7 (c) 2005-200 7::: www.CodeResort.com - BV Network AS (simon-code@bvnetwork.no)7 (c) 2005-2008 ::: www.CodeResort.com - BV Network AS (simon-code@bvnetwork.no) 8 8 (c) 2007 ::: www.Optaros.com (.....) 9 9 """ … … 39 39 'cols': to_unicode(req.args.get('cols')), 40 40 'rows': to_unicode(req.args.get('rows')), 41 'order': req.args.get('order', 0)}41 'order': req.args.get('order', '')} 42 42 return cfdict 43 43 … … 90 90 if key.startswith('order_')]) 91 91 values = dict([(val, True) for val in order.values()]) 92 if len(order) != len(values):93 raise TracError, 'Order numbers must be unique.'94 92 cf = cfapi.get_custom_fields(self.env) 95 93 for cur_cf in cf: -
customfieldadminplugin/0.11/customfieldadmin/templates/customfieldadmin.html
r3420 r4964 139 139 <td>${cf.label}</td> 140 140 <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} 145 145 </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">—</option> 149 <option selected="selected" 150 title="Currently outside regular range">${cf.order}</option> 151 </py:if> 146 152 </select> 147 153 </td>
Note: See TracChangeset
for help on using the changeset viewer.