Ticket #1072: datamoverplugin.patch

File datamoverplugin.patch, 25.9 kB (added by Eridius <kevin@sb.org>, 2 years ago)
  • datamover/util.py

    old new  
     1from trac.core import TracError 
    12from trac.env import Environment 
    23from trac.web.main import _open_environment 
    34from trac.wiki.model import WikiPage 
     5from trac.ticket.model import Component as TicketComponent, Milestone 
    46 
    5 __all__ = ['copy_ticket', 'copy_wiki_page'
     7__all__ = ['copy_ticket', 'copy_wiki_page', 'copy_component', 'copy_enum'
    68 
    79 
    810def make_query(data, table): 
     
    9395        
    9496    if handle_commit: 
    9597        dest_db.commit() 
     98 
     99def copy_component(source_env, dest_env, name, dest_db=None): 
     100    # In case a string gets passed in 
     101    if not isinstance(source_env, Environment): 
     102        source_env = _open_environment(source_env) 
     103    if not isinstance(dest_env, Environment): 
     104        dest_env = _open_environment(dest_env) 
     105         
     106    # Log message 
     107    source_env.log.info('DatamoverPlugin: Moving component %s to the environment at %s', name, dest_env.path) 
     108    dest_env.log.info('DatamoverPlugin: Moving component %s from the environment at %s', name, source_env.path) 
     109     
     110    # Open databases 
     111    source_db = source_env.get_db_cnx() 
     112    source_cursor = source_db.cursor() 
     113    handle_commit = True 
     114    if not dest_db: 
     115        dest_db, handle_commit = dest_env.get_db_cnx(), False 
     116    dest_cursor = dest_db.cursor() 
     117     
     118    # Remove the component from the destination 
     119    try: 
     120        dest_comp = TicketComponent(dest_env, name, db=dest_db) 
     121        if dest_comp.exists: 
     122            dest_comp.delete(db=dest_db) 
     123    except TracError: 
     124        pass 
     125 
     126    # Copy each entry in the component table 
     127    source_cursor.execute('SELECT * FROM component WHERE name=%s',(name,)) 
     128    for row in source_cursor: 
     129        comp_data = dict(zip([d[0] for d in source_cursor.description], row)) 
     130        q = make_query(comp_data, 'component') 
     131        dest_cursor.execute(*q) 
     132        
     133    if handle_commit: 
     134        dest_db.commit() 
     135 
     136def copy_enum(source_env, dest_env, etype, name, dest_db=None): 
     137    # In case a string gets passed in 
     138    if not isinstance(source_env, Environment): 
     139        source_env = _open_environment(source_env) 
     140    if not isinstance(dest_env, Environment): 
     141        dest_env = _open_environment(dest_env) 
     142         
     143    # Log message 
     144    source_env.log.info('DatamoverPlugin: Moving enum (%s,%s) to the environment at %s', etype, name, dest_env.path) 
     145    dest_env.log.info('DatamoverPlugin: Moving enum (%s,%s) from the environment at %s', etype, name, source_env.path) 
     146     
     147    # Open databases 
     148    source_db = source_env.get_db_cnx() 
     149    source_cursor = source_db.cursor() 
     150    handle_commit = True 
     151    if not dest_db: 
     152        dest_db, handle_commit = dest_env.get_db_cnx(), False 
     153    dest_cursor = dest_db.cursor() 
     154     
     155    # Remove the enum from the destination 
     156    dest_cursor.execute('DELETE FROM enum WHERE type=%s AND name=%s', (etype, name)) 
     157 
     158    # Copy each entry in the component table 
     159    source_cursor.execute('SELECT * FROM enum WHERE type=%s AND name=%s',(etype,name)) 
     160    for row in source_cursor: 
     161        comp_data = dict(zip([d[0] for d in source_cursor.description], row)) 
     162        q = make_query(comp_data, 'enum') 
     163        dest_cursor.execute(*q) 
     164        
     165    if handle_commit: 
     166        dest_db.commit() 
     167 
     168def copy_milestone(source_env, dest_env, name, dest_db=None): 
     169    # In case a string gets passed in 
     170    if not isinstance(source_env, Environment): 
     171        source_env = _open_environment(source_env) 
     172    if not isinstance(dest_env, Environment): 
     173        dest_env = _open_environment(dest_env) 
     174         
     175    # Log message 
     176    source_env.log.info('DatamoverPlugin: Moving milestone %s to the environment at %s', name, dest_env.path) 
     177    dest_env.log.info('DatamoverPlugin: Moving milestone %s from the environment at %s', name, source_env.path) 
     178     
     179    # Open databases 
     180    source_db = source_env.get_db_cnx() 
     181    source_cursor = source_db.cursor() 
     182    handle_commit = True 
     183    if not dest_db: 
     184        dest_db, handle_commit = dest_env.get_db_cnx(), False 
     185    dest_cursor = dest_db.cursor() 
     186     
     187    # Remove the milestone from the destination 
     188    try: 
     189        dest_milestone = Milestone(dest_env, name, db=dest_db) 
     190        if dest_milestone.exists: 
     191            dest_milestone.delete(db=dest_db) 
     192    except TracError: 
     193        pass 
     194 
     195    # Copy each entry in the milestone table 
     196    source_cursor.execute('SELECT * FROM milestone WHERE name=%s',(name,)) 
     197    for row in source_cursor: 
     198        comp_data = dict(zip([d[0] for d in source_cursor.description], row)) 
     199        q = make_query(comp_data, 'milestone') 
     200        dest_cursor.execute(*q) 
     201        
     202    if handle_commit: 
     203        dest_db.commit() 
  • datamover/milestone.py

    old new  
     1from trac.core import * 
     2from trac.web.main import _open_environment 
     3from trac.ticket.model import Milestone 
     4 
     5from webadmin.web_ui import IAdminPageProvider 
     6 
     7from api import DatamoverSystem 
     8from util import copy_milestone 
     9 
     10class DatamoverMilestoneModule(Component): 
     11    """The milestone moving component of the datamover plugin.""" 
     12 
     13    implements(IAdminPageProvider) 
     14     
     15    # IAdminPageProvider methods 
     16    def get_admin_pages(self, req): 
     17        if req.perm.has_permission('TRAC_ADMIN'): 
     18            yield ('mover', 'Data Mover', 'milestone', 'Milestones') 
     19     
     20    def process_admin_request(self, req, cat, page, path_info): 
     21        envs = DatamoverSystem(self.env).all_environments() 
     22        milestones = [m.name for m in Milestone.select(self.env)] 
     23         
     24        if req.method == 'POST': 
     25            source_type = req.args.get('source') 
     26            if not source_type or source_type not in ('milestone', 'all'): 
     27                raise TracError, "Source type not specified or invalid" 
     28            source = req.args.get(source_type) 
     29            dest = req.args.get('destination') 
     30            action = None 
     31            if 'copy' in req.args.keys(): 
     32                action = 'copy' 
     33            elif 'move' in req.args.keys(): 
     34                action = 'move' 
     35            else: 
     36                raise TracError, 'Action not specified or invalid' 
     37                 
     38            action_verb = {'copy':'Copied', 'move':'Moved'}[action] 
     39             
     40            comp_filter = None 
     41            if source_type == 'milestone': 
     42                in_milestones = req.args.getlist('milestone') 
     43                milestone_filter = lambda c: c in in_milestones 
     44            elif source_type == 'all': 
     45                milestone_filter = lambda c: True 
     46             
     47            try: 
     48                sel_milestones = [m for m in milestones if milestone_filter(m)] 
     49                dest_db = _open_environment(dest).get_db_cnx() 
     50                for milestone in sel_milestones: 
     51                    copy_milestone(self.env, dest, milestone, dest_db) 
     52                dest_db.commit() 
     53                     
     54                if action == 'move': 
     55                    for milestone in sel_milestones: 
     56                        Milestone(self.env, milestone).delete() 
     57                     
     58                req.hdf['datamover.message'] = '%s milestones %s'%(action_verb, ', '.join(sel_milestones)) 
     59            except TracError, e: 
     60                req.hdf['datamover.message'] = "An error has occured: \n"+str(e) 
     61                self.log.warn(req.hdf['datamover.message'], exc_info=True) 
     62         
     63         
     64        req.hdf['datamover.envs'] = envs 
     65        req.hdf['datamover.milestones'] = milestones 
     66        return 'datamover_milestone.cs', None 
  • datamover/component.py

    old new  
     1from trac.core import * 
     2from trac.web.main import _open_environment 
     3from trac.ticket.model import Component as TicketComponent 
     4 
     5from webadmin.web_ui import IAdminPageProvider 
     6 
     7from api import DatamoverSystem 
     8from util import copy_component 
     9 
     10class DatamoverComponentModule(Component): 
     11    """The ticket component moving component of the datamover plugin.""" 
     12 
     13    implements(IAdminPageProvider) 
     14     
     15    # IAdminPageProvider methods 
     16    def get_admin_pages(self, req): 
     17        if req.perm.has_permission('TRAC_ADMIN'): 
     18            yield ('mover', 'Data Mover', 'component', 'Components') 
     19     
     20    def process_admin_request(self, req, cat, page, path_info): 
     21        envs = DatamoverSystem(self.env).all_environments() 
     22        components = [c.name for c in TicketComponent.select(self.env)] 
     23         
     24        if req.method == 'POST': 
     25            source_type = req.args.get('source') 
     26            if not source_type or source_type not in ('component', 'all'): 
     27                raise TracError, "Source type not specified or invalid" 
     28            source = req.args.get(source_type) 
     29            dest = req.args.get('destination') 
     30            action = None 
     31            if 'copy' in req.args.keys(): 
     32                action = 'copy' 
     33            elif 'move' in req.args.keys(): 
     34                action = 'move' 
     35            else: 
     36                raise TracError, 'Action not specified or invalid' 
     37                 
     38            action_verb = {'copy':'Copied', 'move':'Moved'}[action] 
     39             
     40            comp_filter = None 
     41            if source_type == 'component': 
     42                in_components = req.args.getlist('component') 
     43                comp_filter = lambda c: c in in_components 
     44            elif source_type == 'all': 
     45                comp_filter = lambda c: True 
     46             
     47            try: 
     48                sel_components = [c for c in components if comp_filter(c)] 
     49                dest_db = _open_environment(dest).get_db_cnx() 
     50                for comp in sel_components: 
     51                    copy_component(self.env, dest, comp, dest_db) 
     52                dest_db.commit() 
     53                     
     54                if action == 'move': 
     55                    for comp in sel_components: 
     56                        TicketComponent(self.env, comp).delete() 
     57                     
     58                req.hdf['datamover.message'] = '%s components %s'%(action_verb, ', '.join(sel_components)) 
     59            except TracError, e: 
     60                req.hdf['datamover.message'] = "An error has occured: \n"+str(e) 
     61                self.log.warn(req.hdf['datamover.message'], exc_info=True) 
     62         
     63         
     64        req.hdf['datamover.envs'] = envs 
     65        req.hdf['datamover.components'] = components 
     66        return 'datamover_component.cs', None 
  • datamover/ticket.py

    old new  
    1616    # IAdminPageProvider methods 
    1717    def get_admin_pages(self, req): 
    1818        if req.perm.has_permission('TICKET_ADMIN'): 
    19             yield ('mover', 'Data Mover', 'ticket', 'Ticket') 
     19            yield ('mover', 'Data Mover', 'ticket', 'Tickets') 
    2020     
    2121    def process_admin_request(self, req, cat, page, path_info): 
    2222        components = [c.name for c in TicketComponent.select(self.env)] 
  • datamover/wiki.py

    old new  
    2727         
    2828        if req.method == 'POST': 
    2929            source_type = req.args.get('source') 
    30             if not source_type or source_type not in ('prefix', 'glob', 'regex'): 
     30            if not source_type or source_type not in ('prefix', 'glob', 'regex', 'all'): 
    3131                raise TracError, "Source type not specified or invalid" 
    3232            source = req.args.get(source_type) 
    3333            dest = req.args.get('destination') 
     
    4848                page_filter = lambda p: fnmatch.fnmatch(p, source) 
    4949            elif source_type == 'regex': 
    5050                page_filter = lambda p: re.search(re.compile(source, re.U), p) 
     51            elif source_type == 'all': 
     52                page_filter = lambda p: True 
    5153                 
    5254                             
    5355            try: 
  • datamover/enum.py

    old new  
     1from trac.core import * 
     2from trac.web.main import _open_environment 
     3 
     4from webadmin.web_ui import IAdminPageProvider 
     5 
     6from api import DatamoverSystem 
     7from util import copy_enum 
     8 
     9class DatamoverEnumModule(Component): 
     10    """The ticket enum moving component of the datamover plugin.""" 
     11 
     12    implements(IAdminPageProvider) 
     13     
     14    # IAdminPageProvider methods 
     15    def get_admin_pages(self, req): 
     16        if req.perm.has_permission('TRAC_ADMIN'): 
     17            yield ('mover', 'Data Mover', 'enum', 'Enums') 
     18     
     19    def process_admin_request(self, req, cat, page, path_info): 
     20        envs = DatamoverSystem(self.env).all_environments() 
     21        enums = [] 
     22        source_db = self.env.get_db_cnx() 
     23        source_cursor = source_db.cursor() 
     24        source_cursor.execute('SELECT type,name FROM enum') 
     25        for row in source_cursor: 
     26            enums.append(row) 
     27        hashedEnums = {} 
     28        for enum in enums: 
     29            enum_type = enum[0] 
     30            enum_name = enum[1] 
     31            if not hashedEnums.has_key(enum_type): 
     32                hashedEnums[enum_type] = [] 
     33            hashedEnums[enum_type].append(enum_name) 
     34         
     35        if req.method == 'POST': 
     36            source_type = req.args.get('source') 
     37            if not source_type or source_type not in ('type', 'enum', 'all'): 
     38                raise TracError, "Source type not specified or invalid" 
     39            source = req.args.get(source_type) 
     40            dest = req.args.get('destination') 
     41            action = None 
     42            if 'copy' in req.args.keys(): 
     43                action = 'copy' 
     44            elif 'move' in req.args.keys(): 
     45                action = 'move' 
     46            else: 
     47                raise TracError, 'Action not specified or invalid' 
     48                 
     49            action_verb = {'copy':'Copied', 'move':'Moved'}[action] 
     50             
     51            enum_filter = None 
     52            if source_type == 'type': 
     53                sel_type = req.args.get('enumtype') 
     54                enum_filter = lambda e: e[0] == sel_type 
     55            elif source_type == 'enum': 
     56                sel_enums = [(k,v) for k,v in req.args.items() if k.startswith('enum[')] 
     57                enum_filter = lambda e: ('enum[%s]' % e[0], e[1]) in sel_enums 
     58            elif source_type == 'all': 
     59                enum_filter = lambda c: True 
     60             
     61            try: 
     62                filtered_enums = [e for e in enums if enum_filter(e)] 
     63                dest_db = _open_environment(dest).get_db_cnx() 
     64                for enum in filtered_enums: 
     65                    copy_enum(self.env, dest, enum[0], enum[1], dest_db) 
     66                dest_db.commit() 
     67                     
     68                if action == 'move': 
     69                    for enum in filtered_enums: 
     70                        source_cursor.execute('DELETE FROM enum WHERE type=%s AND name=%s', (enum[0],enum[1])) 
     71                     
     72                req.hdf['datamover.message'] = '%s enums %s'%(action_verb, ', '.join(['%s:%s'%e for e in filtered_enums])) 
     73            except TracError, e: 
     74                req.hdf['datamover.message'] = "An error has occured: \n"+str(e) 
     75                self.log.warn(req.hdf['datamover.message'], exc_info=True) 
     76         
     77         
     78        req.hdf['datamover.envs'] = envs 
     79        for k in hashedEnums: 
     80            req.hdf['datamover.enums.' + k] = hashedEnums[k] 
     81        req.hdf['datamover.enumtypes'] = hashedEnums.keys() 
     82        return 'datamover_enum.cs', None 
  • datamover/templates/datamover_milestone.cs

    old new  
     1<h2>Move Milestones</h2> 
     2 
     3<?cs if:datamover.message ?> 
     4<div id="datamover_message" style="font-weight: bold"> 
     5<?cs var:datamover.message ?> 
     6</div> 
     7<?cs /if ?> 
     8 
     9<form class="mod" method="post" action=""> 
     10 
     11<fieldset> 
     12    <legend>Source</legend> 
     13    <div class="field"> 
     14        <label><input type="radio" name="source" value="milestone" id="source_milestone_radio" checked="checked" /> 
     15            Milestone 
     16        </label> 
     17        <label><input type="radio" name="source" value="all" id="source_all_radio" /> 
     18            All 
     19        </label> 
     20    </div> 
     21    <div class="field" id="source_milestone_div"> 
     22        <label>Milestone: 
     23            <?cs each:milestone = datamover.milestones ?> 
     24            <br/> 
     25            <input type="checkbox" name="milestone" value="<?cs var:milestone ?>"><?cs var:milestone ?></input> 
     26            <?cs /each ?> 
     27        </label> 
     28    </div> 
     29    <div class="field" id="source_all_div" style="display: none"> 
     30        &nbsp; 
     31    </div> 
     32</fieldset> 
     33 
     34<fieldset> 
     35    <legend>Destination</legend> 
     36    <div class="field"> 
     37        <label>Environment: 
     38            <select name="destination"> 
     39                <?cs each:env = datamover.envs ?> 
     40                <option value="<?cs name:env ?>"><?cs var:env.name ?></option> 
     41                <?cs /each ?> 
     42            </select> 
     43        </label> 
     44    </div> 
     45</fieldset> 
     46 
     47<div class="buttons"> 
     48    <input type="submit" name="copy" value="Copy" />&nbsp; 
     49    <input type="submit" name="move" value="Move" /> 
     50</div> 
     51     
     52</form> 
     53     
     54     
     55<script type="text/javascript"> 
     56<!-- 
     57    var current_div = 'source_milestone_div'; 
     58     
     59    function show_div(d) { 
     60        document.getElementById(current_div).style.display = 'none'; 
     61        document.getElementById(d).style.display = 'block'; 
     62        current_div = d; 
     63    } 
     64     
     65    function do_addEvent(d) { 
     66        addEvent(document.getElementById(d+'_radio'), 'click', function() { show_div(d+'_div'); }); 
     67    } 
     68     
     69    do_addEvent('source_milestone'); 
     70    do_addEvent('source_all'); 
     71//--> 
     72</script> 
     73 
  • datamover/templates/datamover_component.cs

    old new  
     1<h2>Move Components</h2> 
     2 
     3<?cs if:datamover.message ?> 
     4<div id="datamover_message" style="font-weight: bold"> 
     5<?cs var:datamover.message ?> 
     6</div> 
     7<?cs /if ?> 
     8 
     9<form class="mod" method="post" action=""> 
     10 
     11<fieldset> 
     12    <legend>Source</legend> 
     13    <div class="field"> 
     14        <label><input type="radio" name="source" value="component" id="source_component_radio" checked="checked" /> 
     15            Component 
     16        </label> 
     17        <label><input type="radio" name="source" value="all" id="source_all_radio" /> 
     18            All 
     19        </label> 
     20    </div> 
     21    <div class="field" id="source_component_div"> 
     22        <label>Component: 
     23            <?cs each:comp = datamover.components ?> 
     24            <br/> 
     25            <input type="checkbox" name="component" value="<?cs var:comp ?>"><?cs var:comp ?></input> 
     26            <?cs /each ?> 
     27        </label> 
     28    </div> 
     29    <div class="field" id="source_all_div" style="display: none"> 
     30        &nbsp; 
     31    </div> 
     32</fieldset> 
     33 
     34<fieldset> 
     35    <legend>Destination</legend> 
     36    <div class="field"> 
     37        <label>Environment: 
     38            <select name="destination"> 
     39                <?cs each:env = datamover.envs ?> 
     40                <option value="<?cs name:env ?>"><?cs var:env.name ?></option> 
     41                <?cs /each ?> 
     42            </select> 
     43        </label> 
     44    </div> 
     45</fieldset> 
     46 
     47<div class="buttons"> 
     48    <input type="submit" name="copy" value="Copy" />&nbsp; 
     49    <input type="submit" name="move" value="Move" /> 
     50</div> 
     51     
     52</form> 
     53     
     54     
     55<script type="text/javascript"> 
     56<!-- 
     57    var current_div = 'source_component_div'; 
     58     
     59    function show_div(d) { 
     60        document.getElementById(current_div).style.display = 'none'; 
     61        document.getElementById(d).style.display = 'block'; 
     62        current_div = d; 
     63    } 
     64     
     65    function do_addEvent(d) { 
     66        addEvent(document.getElementById(d+'_radio'), 'click', function() { show_div(d+'_div'); }); 
     67    } 
     68     
     69    do_addEvent('source_component'); 
     70    do_addEvent('source_all'); 
     71//--> 
     72</script> 
     73 
  • datamover/templates/datamover_ticket.cs

    old new  
    2222        </label> 
    2323        <label><input type="radio" name="source" value="query" id="source_query_radio" /> 
    2424            Query 
    25         </label>        
     25        </label> 
    2626    </div> 
    2727    <div class="field" id="source_component_div"> 
    2828        <label>Component: 
     
    8080    } 
    8181     
    8282    function do_addEvent(d) { 
    83         addEvent(document.getElementById(d+'_radio'), 'change', function() { show_div(d+'_div'); }); 
     83        addEvent(document.getElementById(d+'_radio'), 'click', function() { show_div(d+'_div'); }); 
    8484    } 
    8585     
    8686    do_addEvent('source_component'); 
  • datamover/templates/datamover_wiki.cs

    old new  
    2020        <label><input type="radio" name="source" value="regex" id="source_regex_radio" /> 
    2121            Regex 
    2222        </label> 
     23        <label><input type="radio" name="source" value="all" id="source_all_radio" /> 
     24            All 
     25        </label> 
    2326    </div> 
    2427    <div class="field" id="source_prefix_div"> 
    2528        <label>Prefix: 
     
    3639            <input type="text" name="regex" /> 
    3740        </label> 
    3841    </div> 
     42    <div class="field" id="source_all_div" style="display: none"> 
     43        &nbsp; 
     44    </div> 
    3945</fieldset> 
    4046 
    4147<fieldset> 
     
    7076    } 
    7177     
    7278    function do_addEvent(d) { 
    73         addEvent(document.getElementById(d+'_radio'), 'change', function() { show_div(d+'_div'); }); 
     79        addEvent(document.getElementById(d+'_radio'), 'click', function() { show_div(d+'_div'); }); 
    7480    } 
    7581     
    7682    do_addEvent('source_prefix'); 
    7783    do_addEvent('source_glob'); 
    7884    do_addEvent('source_regex'); 
     85    do_addEvent('source_all'); 
    7986//--> 
    8087</script> 
    8188 
  • datamover/templates/datamover_enum.cs

    old new  
     1<h2>Move Enums</h2> 
     2 
     3<?cs if:datamover.message ?> 
     4<div id="datamover_message" style="font-weight: bold"> 
     5<?cs var:datamover.message ?> 
     6</div> 
     7<?cs /if ?> 
     8 
     9<form class="mod" method="post" action=""> 
     10 
     11<fieldset> 
     12    <legend>Source</legend> 
     13    <div class="field"> 
     14        <label><input type="radio" name="source" value="type" id="source_type_radio" checked="checked" /> 
     15            Enum Type 
     16        </label> 
     17        <label><input type="radio" name="source" value="enum" id="source_enum_radio" /> 
     18            Selected Enums 
     19        </label> 
     20        <label><input type="radio" name="source" value="all" id="source_all_radio" /> 
     21            All 
     22        </label> 
     23    </div> 
     24    <div class="field" id="source_type_div"> 
     25        <label>Enum Type: 
     26            <select name="enumtype"> 
     27                <?cs each:enum = datamover.enums ?> 
     28                <option value="<?cs name:enum ?>"><?cs name:enum ?></option> 
     29                <?cs /each ?> 
     30            </select> 
     31        </label> 
     32    </div> 
     33    <div class="field" id="source_enum_div" style="display: none"> 
     34        <label>Enums: 
     35            <br/> 
     36            <table> 
     37            <?cs each:enum = datamover.enums ?> 
     38            <tr><td valign="top" align="right"><b><?cs name:enum ?>: </b></td> 
     39            <td> 
     40                <?cs each:name = enum ?> 
     41                <input type="checkbox" name="enum[<?cs name:enum ?>]" value="<?cs var:name ?>"><?cs var:name ?></input><br/> 
     42                <?cs /each ?> 
     43            </td></tr> 
     44            <?cs /each ?> 
     45            </table> 
     46        </label> 
     47    </div> 
     48    <div class="field" id="source_all_div" style="display: none"> 
     49        &nbsp; 
     50    </div> 
     51</fieldset> 
     52 
     53<fieldset> 
     54    <legend>Destination</legend> 
     55    <div class="field"> 
     56        <label>Environment: 
     57            <select name="destination"> 
     58                <?cs each:env = datamover.envs ?> 
     59                <option value="<?cs name:env ?>"><?cs var:env.name ?></option> 
     60                <?cs /each ?> 
     61            </select> 
     62        </label> 
     63    </div> 
     64</fieldset> 
     65 
     66<div class="buttons"> 
     67    <input type="submit" name="copy" value="Copy" />&nbsp; 
     68    <input type="submit" name="move" value="Move" /> 
     69</div> 
     70     
     71</form> 
     72     
     73     
     74<script type="text/javascript"> 
     75<!-- 
     76    var current_div = 'source_type_div'; 
     77     
     78    function show_div(d) { 
     79        document.getElementById(current_div).style.display = 'none'; 
     80        document.getElementById(d).style.display = 'block'; 
     81        current_div = d; 
     82    } 
     83     
     84    function do_addEvent(d) { 
     85        addEvent(document.getElementById(d+'_radio'), 'click', function() { show_div(d+'_div'); }); 
     86    } 
     87     
     88    do_addEvent('source_type'); 
     89    do_addEvent('source_enum'); 
     90    do_addEvent('source_all'); 
     91//--> 
     92</script> 
     93 
  • setup.py

    old new  
    55 
    66setup( 
    77    name = 'TracDatamoverPlugin', 
    8     version = '1.1.1', 
     8    version = '1.1.2', 
    99    packages = ['datamover'], 
    1010    package_data={ 'datamover' : [ 'templates/*.cs' ] }, 
    1111    author = "Noah Kantrowitz", 
     
    2222            'datamover.web_ui = datamover.web_ui', 
    2323            'datamover.ticket = datamover.ticket', 
    2424            'datamover.wiki = datamover.wiki', 
     25            'datamover.component = datamover.component', 
     26            'datamover.enum = datamover.enum', 
     27            'datamover.milestone = datamover.milestone', 
    2528        ], 
    2629    }, 
    2730