TracWebAdminDevelopment: 0-8-4-webadmin-patch-with-fixes.diff

File 0-8-4-webadmin-patch-with-fixes.diff, 33.9 kB (added by anonymous, 7 years ago)

Jeoff's patch with some changes/fixes - tested with 0.8.4

  • htdocs/css/admin.css

    old new  
     1 
     2td.targets { 
     3 padding-right: 2em; 
     4} 
     5 
     6#targets_nav ul { 
     7 padding: 0px; 
     8} 
     9 
     10#targets_nav ul li a { 
     11 list-style: none; 
     12 display: block; 
     13 padding: .25em .25em; 
     14 padding-left: 1em; 
     15 padding-right: 1em; 
     16} 
     17 
     18#targets_nav li.target { 
     19 list-style: none; 
     20 border: 1px solid transparent; 
     21} 
     22 
     23#targets_nav li.curr_target {  
     24 list-style: none; 
     25 color: #000;  
     26 background: #f7f7f7; 
     27 border: 1px solid #fb2; 
     28} 
     29 
     30span.curr_target { 
     31 color: red; 
     32} 
     33 
     34table.listing { 
     35 margin-top: 0; 
     36} 
     37 
     38.addnew { 
     39 text-align: center; 
     40 font-size: 85%; 
     41 font-weight: bold; 
     42 border solid 1px lightgray; 
     43} 
     44 
     45/* Styles for the editor form */ 
     46#edit fieldset { margin: 1em 0 } 
     47#edit em { color: #888; font-size: smaller } 
     48#edit .disabled em { color: #d7d7d7 } 
     49#edit .field { margin-top: 1.3em } 
     50#edit label { padding-left: .2em } 
     51#edit textarea#description { width: 97% } 
  • trac/core.py

    old new  
    5959    'attachment'  : ('File', 'Attachment', 0), 
    6060    'roadmap'     : ('Roadmap', 'Roadmap', 0), 
    6161    'settings'    : ('Settings', 'Settings', 0), 
    62     'milestone'   : ('Milestone', 'Milestone', 0) 
     62    'milestone'   : ('Milestone', 'Milestone', 0), 
     63    'admin'       : ('Admin', 'Admin', 0) 
    6364    } 
    6465 
    6566class TracFieldStorage(cgi.FieldStorage): 
     
    127128        if match.group(1): 
    128129            set_if_missing(args, 'id', urllib.unquote(match.group(1))) 
    129130        return args 
     131#    match = re.search('^/admin(?:/([^\?]+))?(?:/(.*)/?)?', path_info) 
     132    match = re.search('^/admin/(general|ticket|user)(?:/([^\?]+))?(?:/(.*)/?)?', path_info) 
     133    if match: 
     134        set_if_missing(args, 'mode', 'admin') 
     135        if match.group(1): 
     136            set_if_missing(args, 'type', match.group(1)) 
     137        if match.group(2): 
     138            set_if_missing(args, 'target', urllib.unquote_plus(match.group(2))) 
     139        return args 
    130140    return args 
    131141 
    132142def parse_args(command, path_info, query_string, 
     
    230240    hdf.setValue('trac.href.login', env.href.login()) 
    231241    hdf.setValue('trac.href.logout', env.href.logout()) 
    232242    hdf.setValue('trac.href.settings', env.href.settings()) 
     243    hdf.setValue('trac.href.admin', env.href.admin('ticket', 'component')) 
    233244    hdf.setValue('trac.href.homepage', 'http://trac.edgewall.com/') 
    234245    hdf.setValue('trac.version', __version__) 
    235246    hdf.setValue('trac.time', time.strftime('%c', time.localtime())) 
  • trac/Admin.py

    old new  
     1# -*- coding: iso8859-1 -*- 
     2# 
     3# Copyright (C) 2005 Edgewall Software 
     4# Copyright (C) 2005 Brad Anderson <brad@dsource.org> 
     5# 
     6# Trac is free software; you can redistribute it and/or 
     7# modify it under the terms of the GNU General Public License as 
     8# published by the Free Software Foundation; either version 2 of the 
     9# License, or (at your option) any later version. 
     10# 
     11# Trac is distributed in the hope that it will be useful, 
     12# but WITHOUT ANY WARRANTY; without even the implied warranty of 
     13# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
     14# General Public License for more details. 
     15# 
     16# You should have received a copy of the GNU General Public License 
     17# along with this program; if not, write to the Free Software 
     18# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
     19# 
     20# Author: Brad Anderson <brad@dsource.org> 
     21 
     22import time 
     23 
     24import perm 
     25import urllib 
     26import string 
     27from util import * 
     28from Module import Module 
     29 
     30 
     31 
     32class Admin(Module): 
     33    template_name = 'admin.cs' 
     34 
     35    def render(self): 
     36         
     37        self.req.hdf.setValue('title', 'Admin') 
     38         
     39        # Commented out general admin, as it does nothing 
     40        #if self.perm.has_permission(perm.TRAC_ADMIN): 
     41        #    self.req.hdf.setValue('admin.general_href', 
     42        #                     self.env.href.admin('general', None)) 
     43         
     44        if self.perm.has_permission(perm.TICKET_ADMIN): 
     45            self.req.hdf.setValue('admin.ticket_href', 
     46                             self.env.href.admin('ticket', 'component')) 
     47         
     48        # Commented out user admin, as it does nothing 
     49        #if self.perm.has_permission(perm.TRAC_ADMIN): 
     50        #    self.req.hdf.setValue('admin.user_href', 
     51        #                     self.env.href.admin('user', 'users')) 
     52                              
     53        type = self.args.get('type', 'ticket').lower() 
     54        self.req.hdf.setValue('admin.type', type) 
     55        self.req.hdf.setValue('admin.path', '/admin/%s/' % type) 
     56         
     57        if type == 'general': 
     58            self.admin = AdminGeneral(self) 
     59        elif type == 'ticket': 
     60            self.admin = AdminTicket(self) 
     61        elif type == 'user': 
     62            self.admin = AdminUser(self) 
     63         
     64        self.admin.render() 
     65         
     66class AdminGeneral(Admin): 
     67    def __init__(self, admin_parent): 
     68        self.req = admin_parent.req 
     69    self.perm = admin_parent.perm 
     70        self.env = admin_parent.env 
     71        self.db = admin_parent.db 
     72        self.args = admin_parent.args 
     73     
     74    def render (self): 
     75        self.perm.assert_permission(perm.TRAC_ADMIN) 
     76         
     77     
     78class AdminTicket(Admin): 
     79    def __init__(self, admin_parent): 
     80    self.req = admin_parent.req 
     81        self.perm = admin_parent.perm 
     82        self.env = admin_parent.env 
     83        self.db = admin_parent.db 
     84    self.args = admin_parent.args 
     85 
     86    def save_attrib(self, target, id): 
     87        self.perm.assert_permission(perm.TRAC_ADMIN) 
     88        if self.args.has_key('save'): 
     89            name = self.args.get('name', '') 
     90            if not name: 
     91                raise TracError('You must provide a name for the %s.' % target, 
     92                                'Required Field Missing') 
     93             
     94            if id == '-1': 
     95                self.create_attrib(target, name) 
     96            else: 
     97                self.update_attrib(target, id, name) 
     98 
     99    def formatVal(self, val, fieldtype): 
     100        """formats the val parameter to be better suited (escaped) for SQL 
     101           strings to be executed by cursor.execute()""" 
     102         
     103        self.env.log.debug("In formatVal, %s" % val) 
     104 
     105        # TODO: handle single and double quotes in val right here 
     106         
     107        # check some things based on metadata, add quotes to val 
     108        if fieldtype == 'date': 
     109            if val == '': 
     110                val = '0' 
     111            else: 
     112                val = "%s" % parse_date(val) 
     113        elif fieldtype in ('string','wiki') and val == '': 
     114            val = 'null' 
     115        else: 
     116            val = "'%s'" % sql_escape(val) 
     117             
     118        return val 
     119         
     120    def create_attrib(self, target, name): 
     121         
     122        self.perm.assert_permission(perm.TRAC_ADMIN) 
     123        cursor = self.db.cursor() 
     124        self.env.log.debug("Creating new %s '%s'" % (target, name)) 
     125         
     126        meta = self.get_attrib_metadata(target) 
     127        fields = meta[0] 
     128        types  = meta[1] 
     129        table  = meta[2] 
     130        where  = meta[3] 
     131        values = [] 
     132         
     133        # loop thru fields, getting values list 
     134    flds = zip(fields, types) 
     135        for f in flds: 
     136            # add to values 
     137            val = self.args.get(f[0], '') 
     138            formattedval = self.formatVal(val, f[1]) 
     139        self.env.log.debug("create_attrib(): field=%s val=%s type=%s fmtd=%s" % (f[0], val, f[1], formattedval) ) 
     140            values.append( formattedval ) 
     141 
     142        # special case for enum 
     143        if table == "enum": 
     144            fields.insert(0, 'type') 
     145            values.insert(0, self.formatVal(target, 'string') ) 
     146             
     147        # self.env.log.debug("create_attrib() fields: %s" % fields) 
     148        # self.env.log.debug("create_attrib() values: %s" % values) 
     149        
     150    fieldlist = string.join(fields, ',') 
     151        valueslist = string.join(values, ',') 
     152                     
     153        # self.env.log.debug("create_attrib() fieldlist : %s" % (fieldlist)) 
     154        # self.env.log.debug("create_attrib() valueslist: %s" % (valueslist)) 
     155         
     156         
     157        sql = "INSERT INTO %s (%s) VALUES (%s)" % (table, fieldlist, valueslist) 
     158        self.env.log.debug("create_attrib() sql      : %s" % (sql))     
     159         
     160        cursor.execute(sql) 
     161        self.db.commit() 
     162        self.req.redirect(self.env.href.admin('ticket', target)) 
     163 
     164    def update_attrib(self, target, id, name): 
     165         
     166        self.perm.assert_permission(perm.TRAC_ADMIN) 
     167        cursor = self.db.cursor() 
     168        self.env.log.debug( "Updating %s '%s'" % (target,id) ) 
     169 
     170        if self.args.has_key('save'): 
     171            self.env.log.info("Updating %s field of all tickets " 
     172                              "associated with %s '%s'" % (target, target, id) ) 
     173            sql = "UPDATE ticket SET %s = '%s' WHERE %s = '%s'" % (target, sql_escape(name), target, sql_escape(id)) 
     174            self.env.log.info("sql: %s" % sql) 
     175            cursor.execute(sql) 
     176            self.db.commit() 
     177 
     178            self.env.log.info("Updating %s '%s' to '%s'" % (target, id, name) ) 
     179            meta = self.get_attrib_metadata(target) 
     180            fields = meta[0] 
     181            types  = meta[1] 
     182            table  = meta[2] 
     183            where  = meta[3] 
     184            set = "" 
     185             
     186            flds = zip(fields,types) 
     187            for f in flds: 
     188                val = self.args.get(f[0], "") 
     189                val = self.formatVal(val, f[1]) 
     190 
     191                self.env.log.debug( "update_attrib:  %s %s" % (f[0],val) ) 
     192                set += ", %s=%s" % (f[0], val) 
     193            set = set[2:] 
     194             
     195            if len(where) > 0: 
     196                where += " and " 
     197            where += "name='%s'" % sql_escape(id) 
     198             
     199            sql = "update %s set %s where %s" % (table, set, where) 
     200            # raise TracError("save_attrib sql: '%s'" % sql) 
     201            cursor.execute(sql) 
     202            self.db.commit() 
     203             
     204            cursor.close() 
     205             
     206        self.req.redirect(self.env.href.admin('ticket', target)) 
     207             
     208    def delete_attrib(self, target, id): 
     209        self.perm.assert_permission(perm.TRAC_ADMIN) 
     210         
     211        if self.args.has_key('delete'): 
     212            cursor = self.db.cursor() 
     213            if self.args.has_key('chk_retarget'): 
     214                retarget = self.args.get('retarget') 
     215                if retarget: 
     216                    self.env.log.info('Retargeting %s field of all ' 
     217                        'tickets associated with %s=%s to %s=%s' %  
     218                        (target, target, id, target, retarget)) 
     219                    sql = "UPDATE ticket SET %s = '%s' WHERE %s = '%s'" % (target, sql_escape(retarget), target, sql_escape(id))  
     220                    self.env.log.debug("retarget SQL: %s" % sql) 
     221                    cursor.execute(sql) 
     222 
     223                else: 
     224                    self.env.log.info('Resetting %s field of all ' 
     225                        'tickets associated with %s=%s' % (target, target, id)) 
     226                    sql = "UPDATE ticket SET %s = NULL WHERE %s = '%s'" % (target, target, sql_escape(id)) 
     227                    self.env.log.debug("sql: %s" % sql) 
     228                    cursor.execute(sql) 
     229 
     230 
     231            self.env.log.debug('Deleting %s %s' % (target, id)) 
     232            meta = self.get_attrib_metadata(target) 
     233            table  = meta[2] 
     234            where  = meta[3] 
     235             
     236            sql  = "DELETE FROM %s " % table 
     237            sql += "WHERE name = %s " % self.formatVal(id, 'string') 
     238            if where: 
     239                sql += "AND %s " % where 
     240            self.env.log.debug('delete_attrib - sql(delete from target ' 
     241                               'table): %s' % (sql)) 
     242            cursor.execute(sql) 
     243            self.db.commit() 
     244             
     245        self.req.redirect(self.env.href.admin('ticket', target)) 
     246         
     247    # all of this info could be in the db as a metadata table 
     248    def get_attrib_metadata(self, target): 
     249         
     250        if target == 'component': 
     251            fields = ['name', 'owner'] 
     252            types = ['string', 'string'] 
     253            table = 'component' 
     254            where = '' 
     255        elif target == 'version': 
     256            fields = ['name', 'time'] 
     257            types = ['string', 'date'] 
     258            table = 'version' 
     259            where = '' 
     260        elif target == 'severity' or target == 'priority' or \ 
     261             target == 'status' or target == 'resolution': 
     262            fields = ['name', 'value'] 
     263            types = ['string', 'string'] 
     264            table='enum' 
     265            where='type = \'%s\'' % target 
     266        elif target == 'milestone': 
     267            fields = ['name', 'time', 'descr'] 
     268            types = ['string', 'date', 'wiki'] 
     269            table = 'milestone' 
     270            where = '' 
     271         
     272        meta = (fields, types, table, where) 
     273        return meta 
     274                 
     275    def get_attrib_data(self, target, id): 
     276        self.env.log.debug("id 1 %s: " % id) 
     277        meta = self.get_attrib_metadata(target) 
     278        fields = meta[0] 
     279        types  = meta[1] 
     280        table  = meta[2] 
     281        where  = meta[3] 
     282 
     283        if id != -1: 
     284            sql_select = string.join(fields, ',') 
     285            sql = 'SELECT %s ' \ 
     286                  'FROM %s ' \ 
     287                  'WHERE name = \'%s\'' % (sql_select, table, sql_escape(id)) 
     288            if where: 
     289                sql += ' and %s' % where 
     290             
     291            self.env.log.debug("sql 1: %s" % sql) 
     292             
     293            cursor = self.db.cursor() 
     294            cursor.execute(sql) 
     295            row = cursor.fetchone() 
     296            cursor.close() 
     297            if not row: 
     298                raise TracError('Attribute \'%s\' does not exist.' % id, 
     299                                'Invalid Attribute') 
     300                                 
     301            values = row 
     302        else: 
     303            # new attrib value, so fill values with blanks 
     304            values = [] 
     305            for field in fields: 
     306                values.append('') 
     307         
     308        return [values, fields, types] 
     309 
     310    def get_target_attributes(self, target='component'): 
     311         
     312        sql_select = '' 
     313     
     314        meta = self.get_attrib_metadata(target) 
     315        fields = meta[0] 
     316        types  = meta[1] 
     317        table  = meta[2] 
     318        where  = meta[3] 
     319         
     320        sql_select = string.join(fields, ',') 
     321        sql = 'SELECT %s ' \ 
     322              'FROM %s ' % (sql_select, table) 
     323        if where: 
     324            sql += 'WHERE %s' % where 
     325         
     326        cursor = self.db.cursor() 
     327        cursor.execute(sql) 
     328         
     329        # FIXME: fetchall should probably not be used. 
     330        info = cursor.fetchall() 
     331        cols = cursor.description 
     332 
     333        return [cols, info, types] 
     334 
     335 
     336    def render (self): 
     337        self.perm.assert_permission(perm.TICKET_ADMIN) 
     338         
     339    target = self.args.get('target', 'component') 
     340        # to highlight the current target on page 
     341    add_to_hdf(target, self.req.hdf, 'admin.curr_target')  
     342        # self.env.log.debug("admin target '%s'" % target) 
     343 
     344        action = self.args.get('action', 'view') 
     345 
     346        if self.args.has_key('id'): 
     347            id = urllib.unquote( self.args.get('id', '') ) 
     348             
     349        # self.env.log.debug("admin id '%s'" % id) 
     350 
     351         
     352        if action == 'new': 
     353            self.render_editor(target, -1) 
     354        elif action == 'edit': 
     355            self.render_editor(target, id) 
     356        elif action == 'delete': 
     357            self.render_confirm(target, id) 
     358        elif action == 'commit_changes': 
     359            self.save_attrib(target, id) 
     360        elif action == 'confirm_delete': 
     361            self.delete_attrib(target, id) 
     362        else: 
     363            self.render_view(target) 
     364 
     365        # menu on left 
     366        targets = ['component', 'version', 'severity', 'priority', 'status', 
     367                   'resolution', 'milestone'] 
     368         
     369        # add custom fields to the list of targets for admin 
     370#  # Until they're moved into a db table and out of ini, don't bother with admin 
     371#        for f in get_custom_fields(self.env): 
     372#            if f['type'] == 'select' or f['type'] == 'radio': 
     373#                target = { 'name': f['name'] } 
     374#                targets.append(target) 
     375 
     376        add_to_hdf(targets, self.req.hdf, 'admin.targets') 
     377 
     378 
     379    def render_confirm(self, target, id): 
     380         
     381        self.req.hdf.setValue('title', 'Attribute: %s' % id) 
     382        self.req.hdf.setValue('admin.mode', 'delete')         
     383         
     384        add_to_hdf(id, self.req.hdf, 'admin.attrib.name') 
     385 
     386        # get choices for retargeting 
     387        meta = self.get_attrib_metadata(target) 
     388        table  = meta[2] 
     389        where  = meta[3] 
     390                 
     391        cursor = self.db.cursor() 
     392        if where: 
     393            where = "AND %s" % where 
     394        else: 
     395            where = "" 
     396        sql = "SELECT name FROM %s WHERE name != '' %s " \ 
     397              "ORDER BY name" % (table, where) 
     398        cursor.execute(sql) 
     399        retargets = [] 
     400        retarget_no = 0 
     401        while 1: 
     402            row = cursor.fetchone() 
     403            if not row: 
     404                break 
     405            self.req.hdf.setValue('retargets.%d' % retarget_no, row['name']) 
     406            retarget_no += 1 
     407        cursor.close() 
     408 
     409    def render_editor(self, target, id=None): 
     410 
     411        data = [] 
     412        [values, fields, types] = \ 
     413            self.get_attrib_data(target, id) 
     414 
     415        for v, f, t in zip(values, fields, types): 
     416            if t == 'date': 
     417                if v == 0 or v == '': 
     418                    v = '' 
     419                else: 
     420                    v = time.strftime('%m/%d/%Y', time.localtime(v)) 
     421            # self.env.log.debug("render_editor: value='%s', field='%s', type='%s'" % (v, f, t)) 
     422            data.append( dict([('fieldname',f),('fieldtype',t),('value',v)]) ) 
     423             
     424        if id == -1: 
     425            self.req.hdf.setValue('title', 'New Attribute') 
     426            self.req.hdf.setValue('admin.mode', 'new') 
     427        else: 
     428            self.req.hdf.setValue('title', 'Attribute: %s' % id) 
     429            self.req.hdf.setValue('admin.mode', 'edit') 
     430         
     431        add_to_hdf(data, self.req.hdf, 'admin.data') 
     432        add_to_hdf(id, self.req.hdf, 'admin.attrib.name') 
     433        add_to_hdf(get_date_format_hint(), self.req.hdf, 'admin.attrib.date_hint') 
     434 
     435    def render_view(self, target): 
     436 
     437        self.req.hdf.setValue('admin.mode', 'view') 
     438 
     439        try: 
     440            [self.cols, self.rows, self.types] = \ 
     441                self.get_target_attributes(target) 
     442        except Exception, e: 
     443            self.error = e 
     444            self.req.hdf.setValue('attrib.message', 
     445                                  'Attribute data error: %s' % e) 
     446            return None 
     447 
     448        # Convert the header info to HDF-format 
     449        idx = 0 
     450        for col in self.cols: 
     451            title=col[0].capitalize() 
     452            prefix = 'attrib.headers.%d' % idx 
     453            self.req.hdf.setValue('%s.real' % prefix, col[0]) 
     454            self.req.hdf.setValue(prefix, title) 
     455             
     456            idx = idx + 1 
     457 
     458        # Convert the rows and cells to HDF-format 
     459        row_idx = 0 
     460        for row in self.rows: 
     461            col_idx = 0 
     462            numrows = len(row) 
     463            for cell in row: 
     464                cell = str(cell) 
     465                column = self.cols[col_idx][0] 
     466                type = self.types[col_idx] 
     467                value = {} 
     468                value['type'] = type 
     469                 
     470                if type == 'date' and cell != 'None' and cell != '0': 
     471                    t = time.localtime(int(cell)) 
     472                    value['date'] = time.strftime('%m/%d/%Y', t) 
     473                    value['time'] = time.strftime('%X', t) 
     474                    value['datetime'] = time.strftime('%c', t) 
     475                    value['gmt'] = time.strftime('%a, %d %b %Y %H:%M:%S GMT', 
     476                                                 time.gmtime(int(cell))) 
     477                         
     478                prefix = 'attrib.items.%d.%s' % (row_idx, str(column)) 
     479                self.req.hdf.setValue(prefix, escape(str(cell))) 
     480                for key in value.keys(): 
     481                    self.req.hdf.setValue(prefix + '.' + key, str(value[key])) 
     482 
     483                col_idx += 1 
     484            row_idx += 1 
     485        self.req.hdf.setValue('attrib.numrows', str(row_idx)) 
     486 
     487class AdminUser(Admin): 
     488    def __init__(self, admin_parent): 
     489        self.req = admin_parent.req 
     490    self.perm = admin_parent.perm 
     491        self.env = admin_parent.env 
     492        self.db = admin_parent.db 
     493        self.args = admin_parent.args 
     494 
     495    def render (self): 
     496        self.perm.assert_permission(perm.TRAC_ADMIN) 
  • trac/Milestone.py

    old new  
    114114                datestr = self.args.get('date', '') 
    115115                date = 0 
    116116                if datestr: 
    117                     date = self.parse_date(datestr) 
     117                    date = parse_date(datestr) 
    118118            descr = self.args.get('descr', '') 
    119119            if not id: 
    120120                self.create_milestone(name, date, descr) 
     
    125125        else: 
    126126            self.req.redirect(self.env.href.roadmap()) 
    127127 
    128     def parse_date(self, datestr): 
    129         seconds = None 
    130         datestr = datestr.strip() 
    131         for format in ['%x %X', '%x, %X', '%X %x', '%X, %x', '%x', '%c', 
    132                        '%b %d, %Y']: 
    133             try: 
    134                 date = time.strptime(datestr, format) 
    135                 seconds = time.mktime(date) 
    136                 break 
    137             except ValueError: 
    138                 continue 
    139         if seconds == None: 
    140             raise TracError('%s is not a known date format.' % datestr, 
    141                             'Invalid Date Format') 
    142         return seconds 
    143  
    144128    def create_milestone(self, name, date=0, descr=''): 
    145129        self.perm.assert_permission(perm.MILESTONE_CREATE) 
    146130        if not name: 
  • trac/util.py

    old new  
    128128    Escapes the given string so that it can be safely used in an SQL 
    129129    statement 
    130130    """ 
    131     return text.replace("'", "''").replace("\\", "\\\\") 
     131    return text.replace("'", "''") 
    132132 
    133133def add_to_hdf(obj, hdf, prefix): 
    134134    """ 
     
    273273               .replace('29', 'DD', 1).replace('10', 'MM') 
    274274 
    275275 
     276def parse_date(datestr): 
     277    seconds = None 
     278    datestr = datestr.strip() 
     279    for format in ['%m/%d/%Y', '%x', '%x %X', '%x, %X', '%X %x', '%X, %x', '%x', '%c', 
     280                   '%b %d, %Y']: 
     281        try: 
     282            date = time.strptime(datestr, format) 
     283            seconds = time.mktime(date) 
     284            break 
     285        except ValueError: 
     286            continue 
     287    if seconds == None: 
     288        raise TracError('%s is not a known date format.' % datestr, 
     289                        'Invalid Date Format') 
     290    return seconds 
     291 
    276292class TracError(Exception): 
    277293    def __init__(self, message, title=None, show_traceback=0): 
    278294        Exception.__init__(self, message) 
  • trac/Href.py

    old new  
    9797            href = href + '?show=' + show 
    9898        return href 
    9999 
     100    def admin(self, type, target): 
     101        if target == None: 
     102            target='' 
     103        href = href_join(self.base, 'admin/%s/%s' % (type, target)) 
     104        return href 
     105 
    100106    def milestone(self, milestone, action=None): 
    101107        params = [] 
    102108        if milestone: 
  • templates/admin.cs

    old new  
     1<?cs set:html.stylesheet = 'css/admin.css' ?> 
     2<?cs include "header.cs"?> 
     3<?cs include "macros.cs"?> 
     4 
     5<div id="ctxtnav" class="nav"> 
     6 <h2>Admin Navigation</h2> 
     7 <ul> 
     8  <?cs if:admin.general_href ?> 
     9   <li><a href="<?cs var:admin.general_href ?>">General Settings</a></li> 
     10  <?cs /if ?> 
     11  <?cs if:admin.ticket_href ?> 
     12   <li><a href="<?cs var:admin.ticket_href ?>">Ticket Attributes</a></li> 
     13  <?cs /if ?> 
     14  <?cs if:admin.user_href ?> 
     15   <li class="last"><a href="<?cs var:admin.user_href ?>">User Management</a></li> 
     16  <?cs /if ?> 
     17 </ul> 
     18</div> 
     19 
     20<?cs if:admin.type == "general" ?> 
     21 <?cs include:"admin-general.cs" ?> 
     22<?cs elif:admin.type == "ticket" ?> 
     23 <?cs include:"admin-ticket.cs" ?> 
     24<?cs elif:admin.type == "user" ?> 
     25 <?cs include:"admin-user.cs" ?> 
     26<?cs /if ?> 
     27 
     28 
     29<div id="help"> 
     30 <strong>Note:</strong> See <a href="<?cs 
     31   var:trac.href.wiki ?>/TracWebAdmin">TracWebAdmin</a> 
     32   for help on using the administration pages. 
     33</div> 
     34 
     35 
     36<?cs include:"footer.cs"?> 
  • templates/header.cs

    old new  
    115115  call:navlink("New Ticket", trac.href.newticket, "newticket", 
    116116               trac.acl.TICKET_CREATE, "7") ?><?cs 
    117117  call:navlink("Search", trac.href.search, "search", 
    118                trac.acl.SEARCH_VIEW, "4") ?></ul> 
     118               trac.acl.SEARCH_VIEW, "4") ?><?cs 
     119  call:navlink("Admin", trac.href.admin, "admin", 
     120               trac.acl.TRAC_ADMIN, "") ?></ul> 
    119121</div> 
    120122 
    121123<div id="main"> 
  • templates/admin-general.cs

    old new  
     1<div id="content" class="admin"> 
     2    <h1>General Settings</h1> 
     3 
     4</div> 
  • templates/admin-user.cs

    old new  
     1<div id="content" class="admin"> 
     2    <h1>User Management</h1> 
     3 
     4</div> 
  • templates/admin-ticket.cs

    old new  
     1<div id="content" class="admin"> 
     2    <h1>Ticket Attributes</h1> 
     3 <table class="admin"> 
     4  <tr> 
     5   <td class="targets" valign="top"> 
     6    <h3>Edit attributes of type:</h3> 
     7    <div id="targets_nav"> 
     8     <ul><?cs each:target = admin.targets ?> 
     9      <li class="<?cs if:target == admin.curr_target ?>curr_target<?cs  
     10       else ?>target<?cs /if ?>"> 
     11       <a href="<?cs var:cgi_location ?><?cs var:admin.path ?><?cs  
     12       var:target ?>"><?cs var:target ?></a> 
     13      </li><?cs /each ?> 
     14     </ul> 
     15    </div> 
     16   </td> 
     17   <td class="attribs" valign="top"> 
     18    <?cs if:admin.mode == "view" ?> 
     19     <h3>Attributes of type:  
     20      <span class="curr_target"><?cs var:admin.curr_target ?></span> 
     21     </h3> 
     22      
     23     <?cs if attrib.message ?> 
     24      <div class="error"><?cs var attrib.message ?></div> 
     25     <?cs else ?> 
     26      <a class="addnew" href="<?cs  
     27       var:cgi_location ?><?cs var:admin.path ?><?cs var:admin.curr_target 
     28       ?>?action=new">add new <?cs var:admin.curr_target ?></a> 
     29      <?cs def:attrib_hdr(header) ?> 
     30       
     31      <table id="attriblist" class="listing" style="margin-top: 0.5em;"> 
     32       <thead> 
     33        <tr> 
     34         <?cs set numcols = #0 ?> 
     35         <?cs each header = attrib.headers ?> 
     36          <?cs if $header ?> 
     37           <th><?cs var:header ?></th> 
     38          <?cs /if ?> 
     39          <?cs set numcols = numcols + #1 ?> 
     40         <?cs /each ?> 
     41         <th colspan="2"></th> 
     42        </tr> 
     43       </thead> 
     44      <?cs /def ?> 
     45  
     46      <?cs def:attrib_cell(class,contents) ?> 
     47       <td class="<?cs var:$class ?>"> 
     48        <?cs if $contents.type == "date" ?> 
     49         <?cs var:$contents.date ?> 
     50        <?cs else ?> 
     51         <?cs var:$contents ?> 
     52        <?cs /if ?> 
     53         
     54       </td> 
     55       <?cs set col = $col + #1 ?> 
     56      <?cs /def ?> 
     57     <?cs /if ?> 
     58      <?cs set idx = #0 ?> 
     59      <?cs set group = '' ?> 
     60  
     61 
     62      <?cs each row = attrib.items ?> 
     63       <?cs if group != row.__group__ || idx == #0 ?> 
     64         <?cs if:idx != #0 ?></tbody><?cs /if ?> 
     65         <?cs set group = row.__group__ ?> 
     66         <?cs call:attrib_hdr(group) ?> 
     67         <tbody> 
     68       <?cs /if ?> 
     69 
     70       <?cs set rstem='' ?> 
     71       <?cs if idx % #2 ?> 
     72         <?cs set row_class=$rstem+'even' ?> 
     73       <?cs else ?> 
     74         <?cs set row_class=$rstem+'odd' ?> 
     75       <?cs /if ?> 
     76 
     77       <tr class="<?cs var: row_class ?>"> 
     78       <?cs set idx = idx + #1 ?> 
     79       <?cs set col = #0 ?> 
     80       <?cs each cell = row ?> 
     81        <?cs if $col == 0 ?> 
     82         <?cs set link = $cell ?> 
     83        <?cs /if ?> 
     84        <?cs call:attrib_cell(name(cell), $cell) ?> 
     85       <?cs /each ?> 
     86       <td><a href="<?cs var:cgi_location ?><?cs var:admin.path ?><?cs 
     87        var:admin.curr_target ?>?id=<?cs var:link ?>&action=edit">edit 
     88        </a></td> 
     89       <td><a href="<?cs var:cgi_location ?><?cs var:admin.path ?><?cs 
     90        var:admin.curr_target ?>?id=<?cs var:link ?>&action=delete">delete 
     91        </a></td> 
     92       </tr> 
     93     <?cs /each ?> 
     94    </tbody> 
     95   </table> 
     96  <?cs if attrib.numrows > 20 ?> 
     97    <a class="addnew" href="<?cs  
     98     var:cgi_location ?><?cs var:admin.path ?><?cs var:admin.curr_target 
     99     ?>?action=new">add new <?cs var:admin.curr_target ?></a> 
     100  <?cs /if ?> 
     101   
     102   
     103    <?cs elif:admin.mode == "edit" || admin.mode == "new" ?> 
     104    <h3><?cs var:admin.mode ?> <?cs var:admin.curr_target ?>: <span  
     105     class="curr_target"> 
     106     <?cs if:admin.mode == "edit" ?><?cs var:admin.attrib.name ?><?cs /if ?> 
     107     </span> 
     108    </h3> 
     109            <form id="edit" action="<?cs var:cgi_location ?>" method="post"> 
     110            <input type="hidden" name="mode" value="admin" /> 
     111            <input type="hidden" name="target" value="<?cs  
     112             var:admin.curr_target ?>" /> 
     113            <input type="hidden" name="id" value="<?cs  
     114             var:admin.attrib.name ?>" /> 
     115            <input type="hidden" name="action" value="commit_changes" /> 
     116      <?cs each:fld = admin.data ?> 
     117       <div class="field"> 
     118        <fieldset class="iefix"> 
     119         <label for="<?cs var:fld.fieldname ?>"><?cs var:fld.fieldname ?><?cs if  
     120          fld.fieldtype == "wiki" ?> (you may use <a tabindex="42" href="<?cs 
     121          var:trac.href.wiki ?>/WikiFormatting">WikiFormatting</a> here):<?cs  
     122          /if ?></label><br /> 
     123         <?cs if fld.fieldtype == "string" ?> 
     124          <input type="text"  
     125           id="<?cs var:fld.fieldname ?>"  
     126           name="<?cs var:fld.fieldname ?>"  
     127           size="32"  
     128           value="<?cs var:fld.value ?>" /> 
     129         <?cs elif fld.fieldtype == "date" ?> 
     130          <input type="text"  
     131           id="<?cs var:fld.fieldname ?>"  
     132           name="<?cs var:fld.fieldname ?>"  
     133           size="32"  
     134           value="<?cs var:fld.value ?>" /> 
     135           <em>Format: <?cs var:admin.attrib.date_hint ?></em> 
     136         <?cs elif fld.fieldtype == "wiki" ?> 
     137          <textarea  
     138           id="<?cs var:fld.fieldname ?>"  
     139           name="<?cs var:fld.fieldname ?>"  
     140           class="wikitext"  
     141           rows="10" cols="78"><?cs var:fld.value ?></textarea> 
     142         <?cs else ?> 
     143          invalid type 
     144         <?cs /if ?> 
     145        </fieldset> 
     146       </div> 
     147      <?cs /each ?> 
     148      <div class="buttons"> 
     149       <?cs if:admin.mode == "new" 
     150        ?><input type="submit" name="save" value="Add Attribute" /><?cs 
     151       else 
     152        ?><input type="submit" name="save" value="Save Changes" /><?cs 
     153       /if ?> 
     154       <input type="submit" name="cancel" value="Cancel" /> 
     155       <?cs if:admin.mode == "edit" ?> 
     156        <p>Note: Changing the field 'name' will result in all tickets with that 
     157          attribute being updated to the new value.</p><?cs /if ?> 
     158      </div> 
     159      <script type="text/javascript" src="<?cs 
     160       var:htdocs_location ?>js/wikitoolbar.js"></script>        
     161     </form> 
     162    <?cs elif:admin.mode == "delete" ?> 
     163    <form id="delete" action="<?cs var:cgi_location ?>" method="post"> 
     164     <input type="hidden" name="mode" value="admin" /> 
     165         <input type="hidden" name="target" value="<?cs  
     166          var:admin.curr_target ?>" /> 
     167         <input type="hidden" name="id" value="<?cs var:admin.attrib.name ?>" /> 
     168         <input type="hidden" name="action" value="confirm_delete" /> 
     169     <p><strong>Are you sure you want to delete <?cs var:admin.curr_target ?>: 
     170      <?cs var:admin.attrib.name ?>?</strong></p> 
     171     <input type="checkbox" id="chk_retarget" name="chk_retarget"  
     172      checked="checked" 
     173      onclick="enableControl('target', this.checked)"/> 
     174     <label for="retarget">Retarget associated tickets to  
     175      <?cs var:admin.curr_target ?></label> 
     176     <select name="retarget" id="retarget"> 
     177      <option value="">None</option><?cs 
     178       each:other = retargets ?><?cs if:other != admin.attrib.name ?> 
     179        <option><?cs var:other ?></option><?cs  
     180       /if ?><?cs /each ?> 
     181     </select> 
     182     <div class="buttons"> 
     183      <input type="submit" name="cancel" value="Cancel" /> 
     184      <input type="submit" name="delete" value= 
     185       "Delete <?cs var:admin.curr_target ?>" /> 
     186     </div> 
     187    </form> 
     188    <?cs /if ?> 
     189   </td> 
     190  </tr> 
     191 </table> 
     192 
     193 
     194 
     195 
     196</div>