TracWebAdminDevelopment: admin-patch-05.diff

File admin-patch-05.diff, 31.8 kB (added by brad <brad@dsource.org>, 7 years ago)

for r1233

  • 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  
    5656    'attachment'  : ('File', 'Attachment', 0), 
    5757    'roadmap'     : ('Roadmap', 'Roadmap', 0), 
    5858    'settings'    : ('Settings', 'Settings', 0), 
    59     'milestone'   : ('Milestone', 'Milestone', 0) 
     59    'milestone'   : ('Milestone', 'Milestone', 0), 
     60    'admin'       : ('Admin', 'Admin', 0) 
    6061    } 
    6162 
    6263class TracFieldStorage(cgi.FieldStorage): 
     
    124125        if match.group(1): 
    125126            set_if_missing(args, 'id', urllib.unquote(match.group(1))) 
    126127        return args 
     128#    match = re.search('^/admin(?:/([^\?]+))?(?:/(.*)/?)?', path_info) 
     129    match = re.search('^/admin/(general|ticket|user)(?:/([^\?]+))?(?:/(.*)/?)?', path_info) 
     130    if match: 
     131        set_if_missing(args, 'mode', 'admin') 
     132        if match.group(1): 
     133            set_if_missing(args, 'type', match.group(1)) 
     134        if match.group(2): 
     135            set_if_missing(args, 'target', urllib.unquote_plus(match.group(2))) 
     136        return args 
    127137    return args 
    128138 
    129139def add_args_to_hdf(args, hdf): 
     
    222232    hdf.setValue('trac.href.login', env.href.login()) 
    223233    hdf.setValue('trac.href.logout', env.href.logout()) 
    224234    hdf.setValue('trac.href.settings', env.href.settings()) 
     235    hdf.setValue('trac.href.admin', env.href.admin('ticket', 'component')) 
    225236    hdf.setValue('trac.href.homepage', 'http://trac.edgewall.com/') 
    226237    hdf.setValue('trac.version', __version__) 
    227238    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, req): 
     36         
     37        req.hdf.setValue('title', 'Admin') 
     38         
     39        if self.perm.has_permission(perm.TRAC_ADMIN): 
     40            req.hdf.setValue('admin.general_href', 
     41                             self.env.href.admin('general', None)) 
     42         
     43        if self.perm.has_permission(perm.TICKET_ADMIN): 
     44            req.hdf.setValue('admin.ticket_href', 
     45                             self.env.href.admin('ticket', 'component')) 
     46         
     47        if self.perm.has_permission(perm.TRAC_ADMIN): 
     48            req.hdf.setValue('admin.user_href', 
     49                             self.env.href.admin('user', 'users')) 
     50                              
     51        type = req.args.get('type', 'ticket').lower() 
     52        req.hdf.setValue('admin.type', type) 
     53        req.hdf.setValue('admin.path', '/admin/%s/' % type) 
     54         
     55        if type == 'general': 
     56            self.admin = AdminGeneral(self.perm, self.env, self.db) 
     57        elif type == 'ticket': 
     58            self.admin = AdminTicket(self.perm, self.env, self.db) 
     59        elif type == 'user': 
     60            self.admin = AdminUser(self.perm, self.env, self.db) 
     61         
     62        self.admin.render(req) 
     63         
     64class AdminGeneral(Admin): 
     65    def __init__(self, perm, env, db): 
     66        self.perm = perm 
     67        self.env = env 
     68        self.db = db 
     69         
     70    def render (self, req): 
     71        self.perm.assert_permission(perm.TRAC_ADMIN) 
     72         
     73     
     74class AdminTicket(Admin): 
     75    def __init__(self, perm, env, db): 
     76        self.perm = perm 
     77        self.env = env 
     78        self.db = db 
     79 
     80    def save_attrib(self, req, target, id): 
     81        self.perm.assert_permission(perm.TRAC_ADMIN) 
     82        if req.args.has_key('save'): 
     83            name = req.args.get('name', '') 
     84            if not name: 
     85                raise TracError('You must provide a name for the %s.' % target, 
     86                                'Required Field Missing') 
     87             
     88            if id == '-1': 
     89                self.create_attrib(req, target, name) 
     90            else: 
     91                self.update_attrib(req, target, id, name) 
     92 
     93    def formatVal(self, val, fieldtype): 
     94        """formats the val parameter to be better suited (escaped) for SQL 
     95           strings to be executed by cursor.execute()""" 
     96         
     97        # TODO: handle single and double quotes in val right here 
     98         
     99        # check some things based on metadata, add quotes to val 
     100        if fieldtype == 'date': 
     101            if val == '': 
     102                val = '0' 
     103            else: 
     104                val = parse_date(val) 
     105        elif fieldtype in ('string','wiki') and val == '': 
     106            val = 'null' 
     107        else: 
     108            val = "'%s'" % val 
     109        return val 
     110         
     111    def create_attrib(self, req, target, name): 
     112         
     113        self.perm.assert_permission(perm.TRAC_ADMIN) 
     114        cursor = self.db.cursor() 
     115        self.env.log.debug("Creating new %s '%s'" % (target, name)) 
     116         
     117        meta = self.get_attrib_metadata(target) 
     118        fields = meta[0] 
     119        types  = meta[1] 
     120        table  = meta[2] 
     121        where  = meta[3] 
     122        values = [] 
     123         
     124        # loop thru fields, getting values list 
     125        flds = zip(fields, types) 
     126        for f in flds: 
     127            # add to values 
     128            val = req.args.get(f[0], '') 
     129            values.append( self.formatVal(val, f[1]) ) 
     130 
     131        # special case for enum 
     132        if table == "enum": 
     133            fields.insert(0, 'type') 
     134            values.insert(0, self.formatVal(target, 'string') ) 
     135             
     136        fieldlist = string.join(fields, ',') 
     137        valueslist = string.join(values, ',') 
     138                     
     139        # self.env.log.debug("create_attrib() fieldlist : %s" % (fieldlist)) 
     140        # self.env.log.debug("create_attrib() valueslist: %s" % (valueslist)) 
     141             
     142        sql = "INSERT INTO %s (%s) VALUES (%s)" % (table, fieldlist, valueslist) 
     143        self.env.log.debug("create_attrib() sql      : %s" % (sql)) 
     144         
     145        cursor.execute(sql) 
     146        self.db.commit() 
     147        req.redirect(self.env.href.admin('ticket', target)) 
     148 
     149    def update_attrib(self, req, target, id, name): 
     150         
     151        self.perm.assert_permission(perm.TRAC_ADMIN) 
     152        cursor = self.db.cursor() 
     153        self.env.log.debug( "Updating %s '%s'" % (target,id) ) 
     154 
     155        if req.args.has_key('save'): 
     156            self.env.log.info("Updating %s field of all tickets " 
     157                              "associated with %s '%s'" % (target, target, id) ) 
     158            cursor.execute("UPDATE ticket SET %s = '%s' " 
     159                           "WHERE %s = '%s'" % (target, name, target, id) ) 
     160            self.db.commit() 
     161 
     162            self.env.log.info("Updating %s '%s' to '%s'" % (target, id, name) ) 
     163            meta = self.get_attrib_metadata(target) 
     164            fields = meta[0] 
     165            types  = meta[1] 
     166            table  = meta[2] 
     167            where  = meta[3] 
     168            set = "" 
     169             
     170            flds = zip(fields,types) 
     171            for f in flds: 
     172                val = req.args.get(f[0], "") 
     173                val = self.formatVal(val, f[1]) 
     174 
     175                self.env.log.debug( "update_attrib:  %s %s" % (f[0],val) ) 
     176                set += ", %s=%s" % (f[0], val) 
     177            set = set[2:] 
     178             
     179            if len(where) > 0: 
     180                where += " and " 
     181            where += "name='%s'" % id 
     182             
     183            sql = "update %s set %s where %s" % (table, set, where) 
     184            # raise TracError("save_attrib sql: '%s'" % sql) 
     185            cursor.execute(sql) 
     186            self.db.commit() 
     187             
     188            cursor.close() 
     189             
     190        req.redirect(self.env.href.admin('ticket', target)) 
     191             
     192    def delete_attrib(self, req, target, id): 
     193        self.perm.assert_permission(perm.TRAC_ADMIN) 
     194         
     195        if req.args.has_key('delete'): 
     196            cursor = self.db.cursor() 
     197            if req.args.has_key('chk_retarget'): 
     198                retarget = req.args.get('retarget') 
     199                if retarget: 
     200                    self.env.log.info('Retargeting %s field of all ' 
     201                        'tickets associated with %s=%s to %s=%s' %  
     202                        (target, target, id, target, retarget)) 
     203                    cursor.execute( 'UPDATE ticket SET %s = %s ' 
     204                        'WHERE %s = %s', (target, retarget, target, id) ) 
     205 
     206                else: 
     207                    self.env.log.info('Resetting %s field of all ' 
     208                        'tickets associated with %s=%s' % (target, target, id)) 
     209                    cursor.execute( 'UPDATE ticket SET %s = NULL ' 
     210                        'WHERE %s = %s', (target, target, id) ) 
     211 
     212 
     213            self.env.log.debug('Deleting %s %s' % (target, id)) 
     214            meta = self.get_attrib_metadata(target) 
     215            table  = meta[2] 
     216            where  = meta[3] 
     217             
     218            sql  = "DELETE FROM %s " % table 
     219            sql += "WHERE name = %s " % self.formatVal(id, 'string') 
     220            if where: 
     221                sql += "AND %s " % where 
     222            self.env.log.debug('delete_attrib - sql(delete from target ' 
     223                               'table): %s' % (sql)) 
     224            cursor.execute(sql) 
     225            self.db.commit() 
     226             
     227        req.redirect(self.env.href.admin('ticket', target)) 
     228         
     229    # all of this info could be in the db as a metadata table 
     230    def get_attrib_metadata(self, target): 
     231         
     232        if target == 'component': 
     233            fields = ['name', 'owner'] 
     234            types = ['string', 'string'] 
     235            table = 'component' 
     236            where = '' 
     237        elif target == 'version': 
     238            fields = ['name', 'time'] 
     239            types = ['string', 'date'] 
     240            table = 'version' 
     241            where = '' 
     242        elif target == 'severity' or target == 'priority' or \ 
     243             target == 'status' or target == 'resolution': 
     244            fields = ['name', 'value'] 
     245            types = ['string', 'string'] 
     246            table='enum' 
     247            where='type = \'%s\'' % target 
     248        elif target == 'milestone': 
     249            fields = ['name', 'due', 'completed', 'description'] 
     250            types = ['string', 'date', 'date', 'wiki'] 
     251            table = 'milestone' 
     252            where = '' 
     253         
     254        meta = (fields, types, table, where) 
     255        return meta 
     256                 
     257    def get_attrib_data(self, target, id): 
     258         
     259        meta = self.get_attrib_metadata(target) 
     260        fields = meta[0] 
     261        types  = meta[1] 
     262        table  = meta[2] 
     263        where  = meta[3] 
     264 
     265        if id != -1: 
     266            sql_select = string.join(fields, ',') 
     267            sql = 'SELECT %s ' \ 
     268                  'FROM %s ' \ 
     269                  'WHERE name = \'%s\'' % (sql_select, table, id) 
     270            if where: 
     271                sql += ' and %s' % where 
     272             
     273            cursor = self.db.cursor() 
     274            cursor.execute(sql) 
     275            row = cursor.fetchone() 
     276            cursor.close() 
     277            if not row: 
     278                raise TracError('Attribute \'%s\' does not exist.' % id, 
     279                                'Invalid Attribute') 
     280                                 
     281            values = row 
     282        else: 
     283            # new attrib value, so fill values with blanks 
     284            values = [] 
     285            for field in fields: 
     286                values.append('') 
     287         
     288        return [values, fields, types] 
     289 
     290    def get_target_attributes(self, target='component'): 
     291         
     292        sql_select = '' 
     293     
     294        meta = self.get_attrib_metadata(target) 
     295        fields = meta[0] 
     296        types  = meta[1] 
     297        table  = meta[2] 
     298        where  = meta[3] 
     299         
     300        sql_select = string.join(fields, ',') 
     301        sql = 'SELECT %s ' \ 
     302              'FROM %s ' % (sql_select, table) 
     303        if where: 
     304            sql += 'WHERE %s' % where 
     305         
     306        cursor = self.db.cursor() 
     307        cursor.execute(sql) 
     308         
     309        # FIXME: fetchall should probably not be used. 
     310        info = cursor.fetchall() 
     311        cols = cursor.description 
     312 
     313        return [cols, info, types] 
     314 
     315 
     316    def render (self, req): 
     317        self.perm.assert_permission(perm.TICKET_ADMIN) 
     318         
     319        target = req.args.get('target', 'component') 
     320        # to highlight the current target on page 
     321        add_to_hdf(target, req.hdf, 'admin.curr_target')  
     322        # self.env.log.debug("admin target '%s'" % target) 
     323 
     324        action = req.args.get('action', 'view') 
     325 
     326        if req.args.has_key('id'): 
     327            id = urllib.unquote( req.args.get('id', '') ) 
     328             
     329        # self.env.log.debug("admin id '%s'" % id) 
     330 
     331         
     332        if action == 'new': 
     333            self.render_editor(req, target, -1) 
     334        elif action == 'edit': 
     335            self.render_editor(req, target, id) 
     336        elif action == 'delete': 
     337            self.render_confirm(req, target, id) 
     338        elif action == 'commit_changes': 
     339            self.save_attrib(req, target, id) 
     340        elif action == 'confirm_delete': 
     341            self.delete_attrib(req, target, id) 
     342        else: 
     343            self.render_view(req, target) 
     344 
     345        # menu on left 
     346        targets = ['component', 'version', 'severity', 'priority', 'status', 
     347                   'resolution', 'milestone'] 
     348         
     349        # add custom fields to the list of targets for admin 
     350#  # Until they're moved into a db table and out of ini, don't bother with admin 
     351#        for f in get_custom_fields(self.env): 
     352#            if f['type'] == 'select' or f['type'] == 'radio': 
     353#                target = { 'name': f['name'] } 
     354#                targets.append(target) 
     355 
     356        add_to_hdf(targets, req.hdf, 'admin.targets') 
     357 
     358 
     359    def render_confirm(self, req, target, id): 
     360         
     361        req.hdf.setValue('title', 'Attribute: %s' % id) 
     362        req.hdf.setValue('admin.mode', 'delete')         
     363         
     364        add_to_hdf(id, req.hdf, 'admin.attrib.name') 
     365 
     366        # get choices for retargeting 
     367        meta = self.get_attrib_metadata(target) 
     368        table  = meta[2] 
     369        where  = meta[3] 
     370                 
     371        cursor = self.db.cursor() 
     372        if where: 
     373            where = "AND %s" % where 
     374        else: 
     375            where = "" 
     376        sql = "SELECT name FROM %s WHERE name != '' %s " \ 
     377              "ORDER BY name" % (table, where) 
     378        cursor.execute(sql) 
     379        retargets = [] 
     380        retarget_no = 0 
     381        while 1: 
     382            row = cursor.fetchone() 
     383            if not row: 
     384                break 
     385            req.hdf.setValue('retargets.%d' % retarget_no, row['name']) 
     386            retarget_no += 1 
     387        cursor.close() 
     388 
     389    def render_editor(self, req, target, id=None): 
     390 
     391        data = [] 
     392        [values, fields, types] = \ 
     393            self.get_attrib_data(target, id) 
     394 
     395        for v, f, t in zip(values, fields, types): 
     396            if t == 'date': 
     397                if v == 0: 
     398                    v = '' 
     399                else: 
     400                    tm = time.localtime(int(v)) 
     401                    v = time.strftime('%x', tm) 
     402            data.append( dict([('fieldname',f),('fieldtype',t),('value',v)]) ) 
     403             
     404        if id == -1: 
     405            req.hdf.setValue('title', 'New Attribute') 
     406            req.hdf.setValue('admin.mode', 'new') 
     407        else: 
     408            req.hdf.setValue('title', 'Attribute: %s' % id) 
     409            req.hdf.setValue('admin.mode', 'edit') 
     410         
     411        add_to_hdf(data, req.hdf, 'admin.data') 
     412        add_to_hdf(id, req.hdf, 'admin.attrib.name') 
     413        add_to_hdf(get_date_format_hint(), req.hdf, 'admin.attrib.date_hint') 
     414 
     415    def render_view(self, req, target): 
     416 
     417        req.hdf.setValue('admin.mode', 'view') 
     418 
     419        try: 
     420            [self.cols, self.rows, self.types] = \ 
     421                self.get_target_attributes(target) 
     422        except Exception, e: 
     423            self.error = e 
     424            req.hdf.setValue('attrib.message', 
     425                                  'Attribute data error: %s' % e) 
     426            return None 
     427 
     428        # Convert the header info to HDF-format 
     429        idx = 0 
     430        for col in self.cols: 
     431            title=col[0].capitalize() 
     432            prefix = 'attrib.headers.%d' % idx 
     433            req.hdf.setValue('%s.real' % prefix, col[0]) 
     434            req.hdf.setValue(prefix, title) 
     435             
     436            idx = idx + 1 
     437 
     438        # Convert the rows and cells to HDF-format 
     439        row_idx = 0 
     440        for row in self.rows: 
     441            col_idx = 0 
     442            numrows = len(row) 
     443            for cell in row: 
     444                cell = str(cell) 
     445                column = self.cols[col_idx][0] 
     446                type = self.types[col_idx] 
     447                value = {} 
     448                value['type'] = type 
     449                 
     450                if type == 'date' and cell != 'None' and cell != '0': 
     451                    t = time.localtime(int(cell)) 
     452                    value['date'] = time.strftime('%x', t) 
     453                    value['time'] = time.strftime('%X', t) 
     454                    value['datetime'] = time.strftime('%c', t) 
     455                    value['gmt'] = time.strftime('%a, %d %b %Y %H:%M:%S GMT', 
     456                                                 time.gmtime(int(cell))) 
     457                         
     458                prefix = 'attrib.items.%d.%s' % (row_idx, str(column)) 
     459                req.hdf.setValue(prefix, escape(str(cell))) 
     460                for key in value.keys(): 
     461                    req.hdf.setValue(prefix + '.' + key, str(value[key])) 
     462 
     463                col_idx += 1 
     464            row_idx += 1 
     465        req.hdf.setValue('attrib.numrows', str(row_idx)) 
     466 
     467class AdminUser(Admin): 
     468    def __init__(self, perm, env, db): 
     469        self.perm = perm 
     470        self.env = env 
     471        self.db = db 
     472 
     473    def render (self, req): 
     474        self.perm.assert_permission(perm.TRAC_ADMIN) 
  • trac/Milestone.py

    old new  
    117117            due = 0 
    118118            due_str = req.args.get('duedate', '') 
    119119            if due_str: 
    120                 due = self.parse_date(due_str) 
     120                due = parse_date(due_str) 
    121121            completed = 0 
    122122            if req.args.has_key('completed'): 
    123123                completed_str = req.args.get('completeddate', '') 
    124124                if completed_str: 
    125                     completed = self.parse_date(completed_str) 
     125                    completed = parse_date(completed_str) 
    126126            description = req.args.get('description', '') 
    127127            if not id: 
    128128                self.create_milestone(req, name, due, completed, description) 
     
    133133        else: 
    134134            req.redirect(self.env.href.roadmap()) 
    135135 
    136     def parse_date(self, datestr): 
    137         seconds = None 
    138         datestr = datestr.strip() 
    139         for format in ['%x %X', '%x, %X', '%X %x', '%X, %x', '%x', '%c', 
    140                        '%b %d, %Y']: 
    141             try: 
    142                 date = time.strptime(datestr, format) 
    143                 seconds = time.mktime(date) 
    144                 break 
    145             except ValueError: 
    146                 continue 
    147         if seconds == None: 
    148             raise TracError('%s is not a known date format.' % datestr, 
    149                             'Invalid Date Format') 
    150         return seconds 
    151  
    152136    def create_milestone(self, req, name, due=0, completed=0, description=''): 
    153137        self.perm.assert_permission(perm.MILESTONE_CREATE) 
    154138        if not name: 
  • trac/util.py

    old new  
    254254               .replace('58', 'ss', 1) 
    255255 
    256256 
     257def parse_date(datestr): 
     258    seconds = None 
     259    datestr = datestr.strip() 
     260    for format in ['%x %X', '%x, %X', '%X %x', '%X, %x', '%x', '%c', 
     261                   '%b %d, %Y']: 
     262        try: 
     263            date = time.strptime(datestr, format) 
     264            seconds = time.mktime(date) 
     265            break 
     266        except ValueError: 
     267            continue 
     268    if seconds == None: 
     269        raise TracError('%s is not a known date format.' % datestr, 
     270                        'Invalid Date Format') 
     271    return seconds 
     272 
    257273class TracError(Exception): 
    258274    def __init__(self, message, title=None, show_traceback=0): 
    259275        Exception.__init__(self, message) 
  • trac/Href.py

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