Changeset 2051


Ignore:
Timestamp:
Oct 6, 2011, 6:11:52 PM (11 years ago)
Author:
tjeerd@…
Message:

New visualization interface

Location:
trunk
Files:
1 added
5 deleted
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/grails-app/views/visualize/index.gsp

    r2034 r2051  
    2222    <style type="text/css">
    2323        /** NEEDED FOR RESOURCES PLUGIN **/
    24         .menu_arrow {background-image: url(${resource(dir: 'images/visualization', file: 'down_arrow.png')}); }
     24        .menu_seperator {background-image: url(${resource(dir: 'images/visualization', file: 'seperator.gif')}); }
    2525        .message_error { background: #ffe0e0 url(${fam.icon( name: 'exclamation' )}) 10px 5px no-repeat; }
    2626        .message_warning { background: #eee url(${fam.icon( name: 'information' )}) 10px 5px no-repeat; }
     
    3939</head>
    4040<body>
    41        
     41
    4242    <div id="data">
    43         <div id="menu_container">
    44             <form id="visualizationForm">
    45                 <div class="menu_spacer"> </div>
    46                 <div class="menu_item menu_item_fill" id="menu_study">
    47                     <div class="menu_item_label">Studies <img src="${resource(dir: 'images', file: 'spinner.gif')}" class="spinner" /></div>
    48                     <div class="menu_item_info"></div>
     43        <form id="visualizationForm">
     44            <div id="top_container">
     45
     46                <span class="menu_seperator">&nbsp;</span>
     47
     48                <span class="topmenu_item" id="menu_study">
     49                    <span class="topmenu_item_label"><img src="${fam.icon( name: 'report' )}" style="vertical-align: text-bottom; display: inline-block;"/>&nbsp;Study<img src="${resource(dir: 'images', file: 'spinner.gif')}" class="spinner" />:</span>
     50                    <span class="topmenu_item_info">no study selected</span>
     51                    <img src="${fam.icon( name: 'bullet_arrow_down' )}" style="vertical-align: text-bottom; display: inline-block;"/>
    4952                    <div class="formulier">
    50                         <g:render template="formStudy" />
    51                         <div style="position: absolute; top: 3px; right: 10px;"><a onClick="hideForm('#menu_study'); return false;" href="#">x</a></div>
     53                        <p class="info">Select a study from the list below.</p>
     54                        <p>
     55                            <g:select from="${studies}" size="4" optionKey="id" optionValue="title" name="study" onChange="changeStudy();"/>
     56                        </p>
     57                    </div>
     58                </span>
     59
     60               
     61
     62                <span class="menu_seperator">&nbsp;</span>
     63
     64                <span class="topmenu_item" id="menu_advanced">
     65                    <span class="topmenu_item_label"><img src="${fam.icon( name: 'cog' )}" style="vertical-align: text-bottom; display: inline-block;"/>&nbsp;Advanced settings</span>
     66                    <img src="${fam.icon( name: 'bullet_arrow_down' )}" style="vertical-align: text-bottom; display: inline-block;"/>
     67                    <div class="formulier">
     68                        <p class="info">Advanced settings.</p>
     69                        <p>
     70                            Visualize the data as soon as enough parameters are known.
     71                            <input type="checkbox" name="autovis" id="autovis" CHECKED/>
     72                        </p>
     73                    </div>
     74                </span>
     75
     76                <span class="menu_seperator">&nbsp;</span>
     77
     78                <span class="topmenu_item" id="message_counter" onClick="; return false;">
     79                    <span class="topmenu_item_label"><img src="${fam.icon( name: 'email_error' )}" style="vertical-align: text-bottom; display: inline-block;"/>&nbsp;Messages:</span>
     80                    <span class="topmenu_item_info">0</span>
     81                    <img src="${fam.icon( name: 'bullet_arrow_down' )}" style="vertical-align: text-bottom; display: inline-block;"/>
     82                    <div class="formulier">
     83                        <p class="info">Messages:</p>
     84                        <div id="message_container">
     85                        <g:if test="${flash.error}">
     86                            <div class="message_box message_error">
     87                                ${flash.error.toString().encodeAsHTML()}
     88                            </div>
     89                        </g:if>
     90                        <g:if test="${flash.message}">
     91                            <div class="message_box message_warning">
     92                                ${flash.message.toString().encodeAsHTML()}
     93                            </div>
     94                        </g:if>
     95                        </div>
     96                    </div>
     97                </span>
     98
     99                <span class="menu_seperator">&nbsp;</span>
     100                   
     101            </div>
     102
     103            <div id="bottom_container">
     104
     105                <div id="menu_container">
     106                    <div class="menu_item" id="menu_column">
     107                        <div class="menu_item_label">X-Axis <img src="${resource(dir: 'images', file: 'spinner.gif')}" class="spinner" /></div>
     108                        <p class="info">Select a field for the X-Axis from the list below. This field will be visible as columns in the table visualization.</p>
     109                        <p>
     110                            <select id="columns" name="columns" size="6" onChange="changeFields('menu_column');"></select>
     111                        </p>
     112                    </div>
     113                    <div class="menu_item" id="menu_row">
     114                        <div class="menu_item_label">Y-Axis <img src="${resource(dir: 'images', file: 'spinner.gif')}" class="spinner" /></div>
     115                        <p class="info">Select a field for the Y-Axis from the list below. This field will be visible as rows in the table visualization.</p>
     116                        <p>
     117                            <select id="rows" name="rows" size="6" onChange="changeFields('menu_row');"></select>
     118                        </p>
     119                    </div>
     120                    <div class="menu_item" id="menu_vis">
     121                        <div class="menu_item_label">Type <img src="${resource(dir: 'images', file: 'spinner.gif')}" class="spinner" /></div>
     122                        <p class="info">Select visualization type.</p>
     123                        <p>
     124                            <select id="types" name="types"  size="3" onChange="changeVis();"></select>
     125                        </p>
     126                    </div>
     127                    <div class="menu_item" id="menu_go">
     128                        <button id="button_visualize" onClick="visualize(); return false;" >
     129                            VISUALIZE
     130                        </button>
    52131                    </div>
    53132                </div>
    54                 <div class="menu_arrow"> </div>
    55                 <div class="menu_item" id="menu_column">
    56                     <div class="menu_item_label">X-Axis <img src="${resource(dir: 'images', file: 'spinner.gif')}" class="spinner" /></div>
    57                     <div class="menu_item_info"></div>
    58                     <div class="formulier">
    59                         <g:render template="formColumns" />
    60                         <div style="position: absolute; top: 3px; right: 10px;"><a onClick="hideForm('#menu_column'); return false;" href="#">x</a></div>
     133               
     134                <div id="visualization_container">
     135                    <div id="visualization"><div style="padding: 30px">Select a study to start.</div>
    61136                    </div>
    62137                </div>
    63                 <div class="menu_item" id="menu_row">
    64                     <div class="menu_item_label">Y-Axis <img src="${resource(dir: 'images', file: 'spinner.gif')}" class="spinner" /></div>
    65                     <div class="menu_item_info"></div>
    66                     <div class="formulier">
    67                         <g:render template="formRows" />
    68                         <div style="position: absolute; top: 3px; right: 10px;"><a onClick="hideForm('#menu_row'); return false;" href="#">x</a></div>
    69                     </div>
    70                 </div>
    71                 <div class="menu_arrow"> </div>
    72                 <div class="menu_item" id="menu_vis">
    73                     <div class="menu_item_label">Type <img src="${resource(dir: 'images', file: 'spinner.gif')}" class="spinner" /></div>
    74                     <div class="menu_item_info"></div>
    75                     <div class="formulier">
    76                         <g:render template="formType" />
    77                         <div style="position: absolute; top: 3px; right: 10px;"><a onClick="hideForm('#menu_vis'); return false;" href="#">x</a></div>
    78                     </div>
    79                 </div>
    80                 <div class="menu_arrow"> </div>
    81                 <div class="menu_item" id="menu_go">
    82                     <button id="button_visualize" onClick="visualize(); return false;" >
    83                         Visualize<br />
    84                         <img src="${resource(dir: 'images', file: 'spinner.gif')}" class="spinner" />
    85                         <span style="height: 16px;">&nbsp;</span>
    86                     </button>
    87                     <input type="checkbox" name="autovis" id="autovis" CHECKED/><span style="font-size: small;">auto</span></div>
    88                 <div class="menu_spacer"> </div>
    89             </form>
    90         </div>
    91138
    92         <div id="visualization_container">
     139                <br clear="all"/>
    93140
    94             <h1>Visualize your study</h1>
    95 
    96             <div id="message_counter" onClick="errorDiv(); return false;">0</div>
    97 
    98             <div id="message_container">
    99                 <g:if test="${flash.error}">
    100                     <div class="message_box message_error">
    101                         ${flash.error.toString().encodeAsHTML()}
    102                     </div>
    103                 </g:if>
    104                 <g:if test="${flash.message}">
    105                     <div class="message_box message_warning">
    106                         ${flash.message.toString().encodeAsHTML()}
    107                     </div>
    108                 </g:if>
    109141            </div>
    110 
    111             <div id="visualization">
    112             </div>
    113         </div>
     142        </form>
    114143    </div>
    115144</body>
  • trunk/web-app/css/visualization.css

    r2048 r2051  
    22.container { width: auto; }
    33#header{ position: relative; width: 960px; margin: 0 auto; }
     4#header .buildinfo{ display: none;}
     5div#content { padding-top: 30px; padding-bottom: 0px;}
     6div#content p {text-align: left;}
    47
    58/* #step2, #step3 { display: none; } */
     
    1013#visualization {
    1114    width: 100%;
     15}
     16
     17#data {
     18    position: relative;
     19    width: 100%;
     20    height: 100%;
     21    background-color: #DFE8F6;
    1222}
    1323
     
    4151
    4252#message_container {
    43     display: none;
     53    position: relative;
     54    min-width: 300px;
    4455}
    4556
    4657.message_box {
    47     width: 750px;
     58    position: relative;
    4859    padding: 5px 35px;
    49     margin: 2px 10px;
     60    margin-bottom: 5px;
    5061}
    5162
     
    5970}
    6071
    61 #message_counter {
     72#message_counter_container {
    6273    position: absolute;
    63     top: 0px;
    64     right: 0px;
    65     padding: 3px;
    66     width: 18px;
    67     height: 18px;
    68     border: 2px solid gray;
    69     text-align: center;
    70     vertical-align: middle;
    71 }
    72 
    73 #message_counter:hover {
     74    right: 3px;
     75}
     76
     77#message_counter_container:hover {
    7478    text-decoration: underline;
    7579    background: #87cefa;
     
    7781}
    7882
    79 div#message_counter.message_warningnew {
     83div#message_counter_container.message_warningnew {
    8084    width: 50px;
    8185    height: 50px;
     
    8387}
    8488
    85 div#message_counter.message_errornew {
     89div#message_counter_container.message_errornew {
    8690    width: 150px;
    8791    height: 150px;
     
    9195/** START :: VISUALIZATION MENU **/
    9296
    93 #data {
    94     position: relative;
    95     width: 960px;
    96 }
    97 
    9897#menu_container {
    99     width : 60px;
    100     background-color: #ddd;
    101     border-top-right-radius: 10px;
    102     -moz-border-radius-topright: 10px;
    103     -webkit-border-top-right-radius: 10px;
    104     border-bottom-right-radius: 10px;
    105     -moz-border-radius-bottomright: 10px;
    106     -webkit-border-bottom-right-radius: 10px;
    107     border-right-style: inset;
    108     border-right-width: 5px;
    109     z-index: 5;
     98    float: left;
     99    width : 19%;
     100    margin: 0% 0% 0% 0.5%;
    110101}
    111102
    112103.menu_item {
    113104    position: relative;
    114     width : 88px;
    115     margin-right: 4px;
    116     padding: 4px;
    117     border-top-right-radius: 10px;
    118     -moz-border-radius-topright: 10px;
    119     -webkit-border-top-right-radius: 10px;
    120     border-bottom-right-radius: 10px;
    121     -moz-border-radius-bottomright: 10px;
    122     -webkit-border-bottom-right-radius: 10px;
    123     border-style: solid solid solid none;
    124     border-width: 2px;
    125     font-size: medium;
    126     background-color: #AAAAAA;
    127     border-color: #888;
    128     z-index: 10;
     105    width : 96%;
     106    margin: 0%;
     107    margin-bottom: 5px;
     108    padding: 2%;
     109    border: #006dba solid 1px;
     110    background-color: white;
    129111    min-height: 60px;
    130 }
    131 
    132 .menu_arrow {
    133     background-repeat: no-repeat;
    134     margin: 6px;
    135     height: 48px;
    136 }
    137 
    138 .menu_spacer {
    139     height: 40px;
     112    font-size: 10px;
     113}
     114
     115.menu_item:hover {
     116    background-color: #EEE;
    140117}
    141118
    142119.menu_item_done {
    143     background-color: #00CC00;
     120    background-color: #67E667;
    144121    border-color: green;
    145122}
     
    156133
    157134.menu_item_fill {
    158     background-color: #87cefa;
     135    background-color: #A5DCFD;
    159136    border-color: blue;
    160137}
    161138
    162 .menu_item_info {
    163     font-size: 9px;
    164     width: 80px;
    165     overflow-x: hidden;
     139.menu_item_label {
     140    font-size: 16px;
     141    color: #006DBA;
    166142}
    167143
    168144#visualization_container {
     145    position: relative;
     146    display: block;
     147    width: 79.5%;
     148    min-height: 500px;
     149    padding: 0px;
     150    margin-top: 5px;
     151    margin-left: 20%;
     152    border: #006dba solid 1px;
     153    background-color: white;
     154}
     155
     156.menu_item select {
     157    width: 100%;
     158    font-size: 10px;
     159}
     160
     161.menu_item p {
     162    margin-bottom: 0px;
     163}
     164
     165#menu_go {
     166    background-color: white;
     167    text-align: center;
     168}
     169
     170/* START :: Top menu */
     171#top_container {
     172    position: relative;
     173    width: 100%;
     174    background-color: #D0DEF0;
     175    border-bottom: #006dba solid 1px;
     176    padding-top: 5px;
     177    height: 25px;
     178    vertical-align: middle;
     179}
     180
     181.topmenu_item {
     182    display: inline-block;
     183    position: relative;
     184    padding: 3px;
     185}
     186
     187.topmenu_item:hover {
     188    background-color: white;
     189    cursor: pointer;
     190}
     191
     192.topmenu_item_label {
     193    color: #000033;
     194}
     195
     196.topmenu_item_info {
     197    color: #000066;
     198}
     199
     200.formulier {
     201    font-size: 10px;
    169202    position: absolute;
    170     left: 120px;
    171     width: 840px;
    172     top: 0px;
    173 
    174 }
    175 
    176 #menu_go {
    177     background-color: white;
    178     width: 110px;
    179 }
    180 
    181 .formulier {
    182     position: absolute;
     203    top: 22px;
     204    left: 0px;
    183205    display: none;
    184     left: 130px;
    185     top: -2px;
    186     width: 360px;
    187     height: 170px;
    188     border-style: solid;
    189     border-color: inherit;
    190     border-width: 2px;
    191     background: white;
    192     padding: 40px;
    193 }
    194 
    195 .formulier .info {
    196     font-size: 11px;
    197     color: #555;
    198 }
    199 
    200 .formulier label {
    201     font-size: 14px;
    202     color: #006DBA;
     206    padding: 10px;
     207    margin: 0px;
     208    background-color: white;
     209    border: #006dba double 1px;
     210    z-index: 10;
    203211}
    204212
    205213.formulier select {
    206214    width: 100%;
     215    font-size: 10px;
     216}
     217
     218.menu_seperator {
     219    background-position: center center;
     220    background-repeat: no-repeat;
     221    width: 4px;
     222    overflow: hidden;
     223    height: 100%;
     224}
     225
     226/** START :: MISC */
     227#bottom_container {
     228    position: relative;
    207229}
    208230
     
    211233    width: 16px;
    212234    height: 16px;
     235    vertical-align: text-bottom;
    213236}
    214237
    215238#button_visualize {
    216     margin: 4px;
     239    margin: 3px;
    217240    padding: 10px;
     241    width: 90%;
    218242    text-align: center;
    219243    background-color: #DD0a0a;
    220244    color: white;
    221     font-weight: bold;
    222 }
     245    font-size: 16pt;
     246}
     247
     248div.formulier {
     249    -moz-box-shadow: 3px 3px 4px #000; /* Firefox/Mozilla */
     250    -webkit-box-shadow: 3px 3px 4px #000; /*Safari/Chrome */
     251    box-shadow: 3px 3px 4px #000; /* Opera & hoe het zou moeten */
     252    /* Voor IE 8 */
     253    -ms-filter: "progid:DXImageTransform.Microsoft.Shadow(Strength=4, Direction=135, Color='#000000')";
     254    /* Voor IE 5.5 - 7 */
     255    filter: progid:DXImageTransform.Microsoft.Shadow(Strength=4, Direction=135, Color='#000000');
     256}
  • trunk/web-app/js/visualization.js

    r2046 r2051  
    77
    88$(document).ready(function() {
    9     $(".menu_item").mouseover(
    10         function() {
    11             showForm(this);
     9
     10    $(".topmenu_item").click(
     11        function(event) {
     12            if(openForm!=null && this!=openForm) {
     13                $(openForm).children('.formulier').hide();
     14            }
     15            $(this).children('.formulier').toggle();
     16            openForm = this;
     17            return false;
    1218                }
    1319    );
    1420
    15     $("#menu_go").unbind('mouseover');
    16 
    17     $("#menu_go").mouseover(
    18         function() {
    19             if(openForm!=null){
    20                 hideForm(openForm);
     21    $(document).keyup(
     22        function(event) {
     23            if ( event.which == 27 && openForm!=null ) {
     24                $(openForm).children('.formulier').hide();
     25                openForm = null;
    2126            }
    2227        }
    2328    );
    24 
    25     $(document).keyup(
    26         function(event) {
    27             if ( event.which == 27 && openForm!=null ) {
    28                 hideForm(openForm);
     29   
     30    $(document).click(
     31        function() {
     32            if(openForm!=null) {
     33                $(openForm).children('.formulier').hide();
     34                openForm = null;
    2935            }
    3036        }
    3137    );
    32     $(document).click(
    33         function(event) {
    34             if(openForm!=null) {
    35                 hideForm(openForm);
    36             }
    37         }
    38     );
    39     $(".menu_item:not(#menu_go)").click(
    40         function(event) {
    41             event.stopPropagation();
    42             return false;
    43         }
    44     );
     38
     39    $(".formulier").click(function(event) {
     40        event.stopPropagation();
     41    });
     42
    4543   
    4644});
     
    5149function changeStudy() {
    5250
    53     hideForm("#menu_study");
     51
     52    $("#menu_study").children('.formulier').hide();
     53    openForm = null;
    5454
    5555    $( '#rows, #columns, #types' ).empty();
     
    5959        visualization.destroy();
    6060
    61     $( "#menu_study" ).addClass("menu_item_fill");
    62 
    63     if($( '#study option:selected' ).val()!="") {
    64         $( "#menu_study" ).find("img.spinner").show();
    65         $( "#menu_study" ).find("div.menu_item_info").html("<br />"+$( '#study option:selected' ).text());
     61    if($( '#study option:selected' ).length>0) {
     62        $( "#menu_row, #menu_column" ).find("img.spinner").show();
     63        $( "#menu_study" ).find("span.topmenu_item_info").html($( '#study option:selected' ).text());
    6664
    6765        executeAjaxCall( "getFields", {
     
    7775                if( data.returnData && data.returnData.studyIds==$( '#study option:selected' ).val() ) {
    7876                    var returnData = data.returnData.fields;
    79 
    80                     clearStep("#menu_study");
    8177
    8278                    var prevCat = "";
     
    9389                    $( "#rows, #columns" ).html(strOptions);
    9490                       
    95                         $( "#menu_study" ).find("div.menu_item_info").html("<br />"+$( '#study option:selected' ).text());
    96                         $( "#menu_study" ).addClass("menu_item_done");
     91                        $( "#menu_study" ).find("span.topmenu_item_info").html($( '#study option:selected' ).text());
     92                    $( "#menu_row, #menu_column" ).find("img.spinner").hide();
    9793                        $( "#menu_row, #menu_column" ).addClass("menu_item_fill");
    9894                }
     
    107103function changeFields(divid) {
    108104
    109     hideForm("#"+divid);
    110 
    111105    var type = "rows";
    112106    if(divid=="menu_column") type = "columns";
    113107
    114     if($( '#'+type+' option:selected' ).val()!="") {
    115 
    116         $( "#"+divid ).find("img.spinner").show();
     108    clearStep("#"+divid);
     109    $( "#"+divid ).addClass("menu_item_done");
     110
     111    if($( '#rows option:selected' ).length>0 && $( '#columns option:selected' ).length>0) {
     112
     113        $( "#menu_vis" ).find("img.spinner").show();
    117114
    118115        executeAjaxCall( "getVisualizationTypes", {
     
    135132                    });
    136133                }
    137 
    138                 clearStep("#"+divid);
    139                 $( "#"+divid ).find("div.menu_item_info").html("<br />"+$( '#'+type+' option:selected' ).text());
    140                 $( "#"+divid ).addClass("menu_item_done");
    141134
    142135                if( $( '#types option' ).length>0 ) {
     
    154147                }
    155148
     149                $( "#menu_vis" ).find("img.spinner").hide();
    156150
    157151            }
    158152        },divid);
    159     } else {
    160         clearStep("#menu_vis, #"+divid);
    161         $( "#"+divid ).addClass("menu_item_fill");
    162153    }
    163154}
     
    168159function changeVis() {
    169160
    170     hideForm("#menu_vis");
    171 
    172     if($( '#types option:selected' ).val()!="") {
     161    if($( '#types option:selected' ).length>0) {
    173162        $( "#menu_vis" ).removeClass().addClass("menu_item menu_item_done");
    174163        visType = $( '#types option:selected' ).text();
    175         $( "#menu_vis" ).find("div.menu_item_info").html("<br />"+visType);
    176164    } else {
    177         $( "#menu_vis" ).find("div.menu_item_info").html("");
    178165        $( "#menu_vis" ).removeClass().addClass("menu_item menu_item_fill");
    179166    }
     167    $( "#menu_go" ).removeClass().addClass("menu_item");
    180168    if($("#autovis").attr("checked")=="checked") {
    181169        visualize();
     
    193181    if(!$( "#menu_vis" ).hasClass("menu_item_done") ||
    194182        !$( "#menu_row" ).hasClass("menu_item_done") ||
    195         !$( "#menu_row" ).hasClass("menu_item_done") ||
    196         !$( "#menu_row" ).hasClass("menu_item_done") ) {
    197 
     183        !$( "#menu_column" ).hasClass("menu_item_done")
     184       ) {
    198185        $( ".menu_item" ).not(".menu_item_done").removeClass().addClass("menu_item menu_item_warning");
    199186    } else {
    200 
    201         $( "#menu_go" ).find("img.spinner").show();
    202187
    203188        executeAjaxCall( "getData", {
     
    447432            $( '#message_container' ).prepend( $( "<div>" ).addClass("message_box "+strClass).html( messages[index] ).css("position","relative").fadeIn().append(newClose) );
    448433    }
    449     $( '#message_counter' ).addClass(strClass+"new");
    450     $( '#message_counter' ).switchClass(strClass+"new","",2000);
    451     $( '#message_counter' ).html($('.message_box').length);
    452 }
    453 
    454 function errorDiv() {
    455     if($( '#message_container' ).css("display")=="none") {
    456         $( '#message_container' ).show("fast");
    457     } else {
    458         $( '#message_container' ).hide("fast");
    459     }
     434    $( '#message_counter' ).children(".topmenu_item_info").html($('.message_box').length);
    460435}
    461436
    462437function removeError(strSelector) {
    463438    $( strSelector ).closest(".message_box").remove();
    464     $( "#message_counter" ).html($(".message_box").length);
     439    $( '#message_counter' ).children(".topmenu_item_info").html($(".message_box").length);
    465440    if($(".message_box").length==0) {
    466         errorDiv();
    467     }
    468 }
    469 
    470 function showForm(strSelector) {
    471     if(openForm!=null) {
    472         hideForm(openForm);
    473     }
    474     $( strSelector ).css("width","150px");
    475     $( strSelector ).css("background-color","white");
    476     $( strSelector ).find("div.formulier").show();
    477     openForm = strSelector;
    478 }
    479 
    480 function hideForm(strSelector) {
    481     $( strSelector ).css("width","88px");
    482     $( strSelector ).css("background-color","");
    483     $( strSelector ).find("div.formulier").hide();
    484     openForm = null;
    485 }
    486 
     441        $( '#message_counter' ).children(".formulier").toggle();
     442        openForm = null;
     443    }
     444}
    487445
    488446/**
Note: See TracChangeset for help on using the changeset viewer.