Making WordPress.org

Changeset 1156


Ignore:
Timestamp:
01/16/2015 10:48:01 PM (12 years ago)
Author:
obenland
Message:

WP.org Themes: Improve server-side rendering of themes.

  • Takes into account all possible views.
  • Actually render markup for single themes.

See #745.

Location:
sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-themes
Files:
1 deleted
3 edited

Legend:

Unmodified
Added
Removed
  • sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-themes/content-single.php

    r1087 r1156  
    1 <?php
    2 include ABSPATH . 'wp-admin/includes/theme.php';
    3 $theme = themes_api( 'theme_information', array( 'slug' => get_post()->post_name ) );
    4 ?>
    5 <div id="themes" class="wrap">
    6         <div class="theme-wrap">
    7                 <div class="theme-about">
     1<?php global $theme; ?>
     2<div class="theme-wrap">
     3        <div class="theme-about">
    84
    9                         <?php if ( strtotime( '-2 years' ) > strtotime( $theme->last_updated ) ) : ?>
    10                                 <div class="theme-notice notice notice-warning">
    11                                         <p><?php _e( 'This theme <strong>hasn&#146;t been updated in over 2 years</strong>. It may no longer be maintained or supported and may have compatibility issues when used with more recent versions of WordPress.', 'wporg-themes' ); ?></p>
    12                                 </div><!-- .theme-info -->
    13                         <?php endif; ?>
     5                <?php if ( strtotime( '-2 years' ) > strtotime( $theme->last_updated ) ) : ?>
     6                        <div class="theme-notice notice notice-warning">
     7                                <p><?php _e( 'This theme <strong>hasn&#146;t been updated in over 2 years</strong>. It may no longer be maintained or supported and may have compatibility issues when used with more recent versions of WordPress.', 'wporg-themes' ); ?></p>
     8                        </div><!-- .theme-info -->
     9                <?php endif; ?>
    1410
    15                         <div class="theme-screenshots">
    16                                 <div class="screenshot"><?php the_post_thumbnail(); ?></div>
     11                <div class="theme-screenshots">
     12                        <div class="screenshot"><?php the_post_thumbnail(); ?></div>
    1713
    18                                 <div class="theme-actions">
    19                                         <a href="<?php echo esc_url( '//downloads.wordpress.org/theme/' . $theme->slug . '.' . $theme->version . '.zip' ); ?>" class="button button-primary"><?php _e( 'Download' ); ?></a>
    20                                         <a href="<?php echo esc_url( $theme->preview_url ); ?>" class="button button-secondary"><?php _e( 'Preview' ); ?></a>
     14                        <div class="theme-actions">
     15                                <a href="<?php echo esc_url( '//downloads.wordpress.org/theme/' . $theme->slug . '.' . $theme->version . '.zip' ); ?>" class="button button-primary"><?php _e( 'Download' ); ?></a>
     16                                <a href="<?php echo esc_url( $theme->preview_url ); ?>" class="button button-secondary"><?php _e( 'Preview' ); ?></a>
     17                        </div>
     18                </div><!-- .theme-screenshots -->
     19
     20                <div class="theme-info">
     21                        <div class="hentry">
     22                                <h3 class="theme-name entry-title"><?php the_title(); ?></h3>
     23                                <span class="theme-version">
     24                                        <?php
     25                                                printf( __( 'Version: %s' ),
     26                                                        sprintf( '<abbr title="%1$s">%2$s</abbr>',
     27                                                                esc_attr( sprintf( __( 'Last updated: %s' ), date_i18n( get_option( 'date_format' ), strtotime( $theme->last_updated ) ) ) ),
     28                                                                $theme->version
     29                                                        )
     30                                                );
     31                                        ?>
     32                                </span>
     33                                <h4 class="theme-author"><?php printf( __( 'By %s' ), '<span class="author">' . $theme->author . '</span>' ); ?></h4>
     34
     35                                <div class="theme-description entry-summary"><?php the_content(); ?></div>
     36
     37                                <?php if ( ! empty( $theme->parent ) ) : ?>
     38                                <div class="theme-notice notice notice-info">
     39                                        <p class="parent-theme"><?php printf( __( 'This is a child theme of %s.' ), sprintf( '<a href="/%1$s">%2$s</a>', $theme->parent->slug, $theme->parent->name ) ); ?></p>
    2140                                </div>
    22                         </div><!-- .theme-screenshots -->
     41                                <?php endif; ?>
     42                        </div><!-- .theme-info -->
    2343
    24                         <div class="theme-info">
    25                                 <div class="hentry">
    26                                         <h3 class="theme-name entry-title"><?php the_title(); ?></h3>
    27                                         <span class="theme-version">
    28                                                 <?php
    29                                                         printf( __( 'Version: %s' ),
    30                                                                 sprintf( '<abbr title="%1$s">%2$s</abbr>',
    31                                                                         esc_attr( sprintf( __( 'Last updated: %s' ), date_i18n( get_option( 'date_format' ), strtotime( $theme->last_updated ) ) ) ),
    32                                                                         $theme->version
    33                                                                 )
    34                                                         );
    35                                                 ?>
    36                                         </span>
    37                                         <h4 class="theme-author"><?php printf( __( 'By %s' ), '<span class="author">' . $theme->author . '</span>' ); ?></h4>
     44                        <div class="theme-ratings" itemprop="aggregateRating" itemscope itemtype="http://schema.org/AggregateRating">
     45                                <meta itemprop="ratingValue" content="<?php echo esc_attr( number_format_i18n( $theme->rating / 20, 1 ) ); ?>"/>
     46                                <meta itemprop="ratingCount" content="<?php echo esc_attr( $theme->num_ratings ); ?>"/>
     47                                <h4><?php _e( 'Ratings', 'wporg-themes' ); ?></h4>
    3848
    39                                         <div class="theme-description entry-summary"><?php the_content(); ?></div>
     49                                <div class="star-holder">
     50                                        <div class="star-rating" style="width: <?php echo esc_attr( number_format_i18n( $theme->rating, 1 ) ); ?>%">
     51                                                <?php printf( __( '%d stars', 'wporg-themes' ), number_format_i18n( $theme->rating / 20 ) ); ?>
     52                                        </div>
     53                                </div>
     54                                <span><?php printf( __( '%s out of 5 stars.', 'wporg-themes' ), number_format_i18n( $theme->rating / 20, 1 ) ); ?></span>
    4055
    41                                         <?php if ( ! empty( $theme->parent ) ) : ?>
    42                                         <div class="theme-notice notice notice-info">
    43                                                 <p class="parent-theme"><?php printf( __( 'This is a child theme of %s.' ), sprintf( '<a href="/%1$s">%2$s</a>', $theme->parent->slug, $theme->parent->name ) ); ?></p>
    44                                         </div>
    45                                         <?php endif; ?>
    46                                 </div><!-- .theme-info -->
     56                                <?php
     57                                        if ( ! empty( $theme->ratings ) && ! empty( $theme->num_ratings ) ) :
     58                                                foreach ( $theme->ratings as $key => $rate_count ) :
     59                                ?>
     60                                <div class="counter-container">
     61                                        <a href="//wordpress.org/support/view/theme-reviews/<?php echo esc_attr( $theme->slug ); ?>?filter=<?php echo $key; ?>" title="<?php printf( _n( 'Click to see reviews that provided a rating of %d star', 'Click to see reviews that provided a rating of %d stars', $key, 'wporg-themes' ), $key ); ?>">
     62                                                <span class="counter-label"><?php printf( __( '%d stars', 'wporg-themes' ), $key ); ?></span>
     63                                                <span class="counter-back">
     64                                                        <span class="counter-bar" style="width: <?php echo 92 * ( $rate_count / $theme->num_ratings ); ?>px;"></span>
     65                                                </span>
     66                                        </a>
     67                                        <span class="counter-count"><?php echo $rate_count; ?></span>
     68                                </div>
     69                                <?php
     70                                                endforeach;
     71                                        endif;
     72                                ?>
     73                        </div><!-- .theme-rating -->
    4774
    48                                 <div class="theme-ratings" itemprop="aggregateRating" itemscope itemtype="http://schema.org/AggregateRating">
    49                                         <meta itemprop="ratingValue" content="<?php echo esc_attr( number_format_i18n( $theme->rating / 20, 1 ) ); ?>"/>
    50                                         <meta itemprop="ratingCount" content="<?php echo esc_attr( $theme->num_ratings ); ?>"/>
    51                                         <h4><?php _e( 'Ratings', 'wporg-themes' ); ?></h4>
     75                        <div class="theme-devs">
     76                                <h4><?php _e( 'Development', 'wporg-themes' ); ?></h4>
     77                                <h5><?php _e( 'Subscribe', 'wporg-themes' ); ?></h5>
     78                                <ul class="unmarked-list">
     79                                        <li>
     80                                                <a href="//themes.trac.wordpress.org/log/<?php echo esc_attr( $theme->slug ); ?>?limit=100&mode=stop_on_copy&format=rss">
     81                                                        <img src="//s.w.org/style/images/feedicon.png" style="vertical-align:text-top;"/>
     82                                                        <?php _e( 'Development Log', 'wporg' ); ?>
     83                                                </a>
     84                                        </li>
     85                                </ul>
    5286
    53                                         <div class="star-holder">
    54                                                 <div class="star-rating" style="width: <?php echo esc_attr( number_format_i18n( $theme->rating, 1 ) ); ?>%">
    55                                                         <?php printf( __( '%d stars', 'wporg-themes' ), number_format_i18n( $theme->rating / 20 ) ); ?>
    56                                                 </div>
    57                                         </div>
    58                                         <span><?php printf( __( '%s out of 5 stars.', 'wporg-themes' ), number_format_i18n( $theme->rating / 20, 1 ) ); ?></span>
     87                                <h5><?php _e( 'Browse the Code', 'wporg-themes' ); ?></h5>
     88                                <ul class="unmarked-list">
     89                                        <li><a href="//themes.trac.wordpress.org/log/<?php echo esc_attr( $theme->slug ); ?>/" rel="nofollow"><?php _e( 'Development Log', 'wporg-themes' ); ?></a></li>
     90                                        <li><a href="//themes.svn.wordpress.org/<?php echo esc_attr( $theme->slug ); ?>/" rel="nofollow"><?php _e( 'Subversion Repository', 'wporg-themes' ); ?></a></li>
     91                                        <li><a href="//themes.trac.wordpress.org/browser/<?php echo esc_attr( $theme->slug ); ?>/" rel="nofollow"><?php _e( 'Browse in Trac', 'wporg-themes' ); ?></a></li>
     92                                </ul>
     93                        </div><!-- .theme-devs -->
    5994
    60                                         <?php
    61                                                 if ( ! empty( $theme->ratings ) ) :
    62                                                         foreach ( $theme->ratings as $key => $rate_count ) :
    63                                         ?>
    64                                         <div class="counter-container">
    65                                                 <a href="//wordpress.org/support/view/theme-reviews/<?php echo esc_attr( $theme->slug ); ?>?filter=<?php echo $key; ?>" title="<?php printf( _n( 'Click to see reviews that provided a rating of %d star', 'Click to see reviews that provided a rating of %d stars', $key, 'wporg-themes' ), $key ); ?>">
    66                                                         <span class="counter-label"><?php printf( __( '%d stars', 'wporg-themes' ), $key ); ?></span>
    67                                                         <span class="counter-back">
    68                                                                 <span class="counter-bar" style="width: <?php echo 92 * ( $rate_count / $theme->num_ratings ); ?>px;"></span>
    69                                                         </span>
    70                                                 </a>
    71                                                 <span class="counter-count"><?php echo $rate_count; ?></span>
    72                                         </div>
    73                                         <?php
    74                                                         endforeach;
    75                                                 endif;
    76                                         ?>
    77                                 </div><!-- .theme-rating -->
     95                        <div class="theme-downloads">
     96                                <h4><?php _e( 'Downloads', 'wporg-themes' ); ?></h4>
    7897
    79                                 <div class="theme-devs">
    80                                         <h4><?php _e( 'Development', 'wporg-themes' ); ?></h4>
    81                                         <h5><?php _e( 'Subscribe', 'wporg-themes' ); ?></h5>
    82                                         <ul class="unmarked-list">
    83                                                 <li>
    84                                                         <a href="//themes.trac.wordpress.org/log/<?php echo esc_attr( $theme->slug ); ?>?limit=100&mode=stop_on_copy&format=rss">
    85                                                                 <img src="//s.w.org/style/images/feedicon.png" style="vertical-align:text-top;"/>
    86                                                                 <?php _e( 'Development Log', 'wporg' ); ?>
    87                                                         </a>
    88                                                 </li>
    89                                         </ul>
     98                                <div id="theme-download-stats-<?php echo esc_attr( $theme->slug ); ?>" class="chart"></div>
     99                                <script type="text/javascript">
     100                                        google.load("visualization", "1", {packages:["corechart"]});
     101                                        google.setOnLoadCallback(drawThemeDownloadsChart);
    90102
    91                                         <h5><?php _e( 'Browse the Code', 'wporg-themes' ); ?></h5>
    92                                         <ul class="unmarked-list">
    93                                                 <li><a href="//themes.trac.wordpress.org/log/<?php echo esc_attr( $theme->slug ); ?>/" rel="nofollow"><?php _e( 'Development Log', 'wporg-themes' ); ?></a></li>
    94                                                 <li><a href="//themes.svn.wordpress.org/<?php echo esc_attr( $theme->slug ); ?>/" rel="nofollow"><?php _e( 'Subversion Repository', 'wporg-themes' ); ?></a></li>
    95                                                 <li><a href="//themes.trac.wordpress.org/browser/<?php echo esc_attr( $theme->slug ); ?>/" rel="nofollow"><?php _e( 'Browse in Trac', 'wporg-themes' ); ?></a></li>
    96                                         </ul>
    97                                 </div><!-- .theme-devs -->
     103                                        function drawThemeDownloadsChart() {
     104                                                jQuery(document).ready(function($){
     105                                                        jQuery.getJSON('https://api.wordpress.org/stats/themes/1.0/downloads.php?slug=<?php echo $theme->slug; ?>&limit=267&callback=?', function (downloads) {
     106                                                                var data = new google.visualization.DataTable(),
     107                                                                        count = 0,
     108                                                                        sml;
    98109
    99                                 <div class="theme-downloads">
    100                                         <h4><?php _e( 'Downloads', 'wporg-themes' ); ?></h4>
     110                                                                data.addColumn('string', _wpThemeSettings.l10n.date);
     111                                                                data.addColumn('number', _wpThemeSettings.l10n.downloads);
    101112
    102                                         <div id="theme-download-stats-<?php echo esc_attr( $theme->slug ); ?>" class="chart"></div>
    103                                         <script type="text/javascript">
    104                                                 google.load("visualization", "1", {packages:["corechart"]});
    105                                                 google.setOnLoadCallback(drawThemeDownloadsChart);
     113                                                                $.each(downloads, function (key, value) {
     114                                                                        data.addRow();
     115                                                                        data.setValue(count, 0, new Date(key).toLocaleDateString() );
     116                                                                        data.setValue(count, 1, Number(value));
     117                                                                        count++;
     118                                                                });
    106119
    107                                                 function drawThemeDownloadsChart() {
    108                                                         jQuery(document).ready(function($){
    109                                                                 jQuery.getJSON('https://api.wordpress.org/stats/themes/1.0/downloads.php?slug=<?php echo $theme->slug; ?>&limit=267&callback=?', function (downloads) {
    110                                                                         var data = new google.visualization.DataTable(),
    111                                                                                 count = 0,
    112                                                                                 sml;
     120                                                                sml = data.getNumberOfRows() < 225;
    113121
    114                                                                         data.addColumn('string', _wpThemeSettings.l10n.date);
    115                                                                         data.addColumn('number', _wpThemeSettings.l10n.downloads);
    116 
    117                                                                         $.each(downloads, function (key, value) {
    118                                                                                 data.addRow();
    119                                                                                 data.setValue(count, 0, new Date(key).toLocaleDateString() );
    120                                                                                 data.setValue(count, 1, Number(value));
    121                                                                                 count++;
    122                                                                         });
    123 
    124                                                                         sml = data.getNumberOfRows() < 225;
    125 
    126                                                                         new google.visualization.ColumnChart(document.getElementById('theme-download-stats-<?php echo esc_attr( $theme->slug ); ?>')).draw(data, {
    127                                                                                 colors: ['#253578'],
    128                                                                                 legend: {
    129                                                                                         position: 'none'
    130                                                                                 },
    131                                                                                 titlePosition: 'in',
    132                                                                                 axisTitlesPosition: 'in',
    133                                                                                 chartArea: {
    134                                                                                         height: 280,
    135                                                                                         left: sml ? 30 : 0,
    136                                                                                         width: sml ? '80%' : '100%'
    137                                                                                 },
    138                                                                                 hAxis: {
    139                                                                                         textStyle: {color: 'black', fontSize: 9}
    140                                                                                 },
    141                                                                                 vAxis: {
    142                                                                                         format: '###,###',
    143                                                                                         textPosition: sml ? 'out' : 'in',
    144                                                                                         viewWindowMode: 'explicit',
    145                                                                                         viewWindow: {min: 0}
    146                                                                                 },
    147                                                                                 bar: {
    148                                                                                         groupWidth: ( data.getNumberOfRows() > 100 ) ? "100%" : null
    149                                                                                 },
    150                                                                                 height: 350
    151                                                                         });
     122                                                                new google.visualization.ColumnChart(document.getElementById('theme-download-stats-<?php echo esc_attr( $theme->slug ); ?>')).draw(data, {
     123                                                                        colors: ['#253578'],
     124                                                                        legend: {
     125                                                                                position: 'none'
     126                                                                        },
     127                                                                        titlePosition: 'in',
     128                                                                        axisTitlesPosition: 'in',
     129                                                                        chartArea: {
     130                                                                                height: 280,
     131                                                                                left: sml ? 30 : 0,
     132                                                                                width: sml ? '80%' : '100%'
     133                                                                        },
     134                                                                        hAxis: {
     135                                                                                textStyle: {color: 'black', fontSize: 9}
     136                                                                        },
     137                                                                        vAxis: {
     138                                                                                format: '###,###',
     139                                                                                textPosition: sml ? 'out' : 'in',
     140                                                                                viewWindowMode: 'explicit',
     141                                                                                viewWindow: {min: 0}
     142                                                                        },
     143                                                                        bar: {
     144                                                                                groupWidth: ( data.getNumberOfRows() > 100 ) ? "100%" : null
     145                                                                        },
     146                                                                        height: 350
    152147                                                                });
    153148                                                        });
    154                                                 }
    155                                         </script>
    156                                         <p class="total-downloads"><?php printf( __( 'Total downloads: %s' ), '<strong>' . number_format_i18n( $theme->downloaded ) . '</strong>' ); ?></p>
    157                                 </div><!-- .theme-downloads -->
     149                                                });
     150                                        }
     151                                </script>
     152                                <p class="total-downloads"><?php printf( __( 'Total downloads: %s' ), '<strong>' . number_format_i18n( $theme->downloaded ) . '</strong>' ); ?></p>
     153                        </div><!-- .theme-downloads -->
    158154
    159                                 <div class="theme-tags">
    160                                         <h4><?php _e( 'Tags:' ); ?></h4>
    161                                         <?php
    162                                                 foreach( $theme->tags as &$tag ) :
    163                                                         $tag = sprintf( '<a href="/tag/%1$s/">%1$s</a>', $tag );
    164                                                 endforeach;
    165                                                 echo implode( ', ', $theme->tags );
    166                                         ?>
    167                                 </div><!-- .theme-tags -->
    168                         </div>
     155                        <div class="theme-tags">
     156                                <h4><?php _e( 'Tags:' ); ?></h4>
     157                                <?php
     158                                        foreach( $theme->tags as &$tag ) :
     159                                                $tag = sprintf( '<a href="/tag/%1$s/">%1$s</a>', $tag );
     160                                        endforeach;
     161                                        echo implode( ', ', $theme->tags );
     162                                ?>
     163                        </div><!-- .theme-tags -->
    169164                </div>
    170165        </div>
  • sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-themes/functions.php

    r1148 r1156  
    1515 */
    1616function wporg_themes_setup() {
    17         global $themes_allowedtags, $theme_field_defaults;
     17        global $themes_allowedtags;
    1818
    1919        load_theme_textdomain( 'wporg-themes' );
     
    5151                'img'     => array( 'src' => array(), 'class' => array(), 'alt' => array() ),
    5252        );
    53 
    54         $theme_field_defaults = array(
    55                 'description'  => true,
    56                 'sections'     => false,
    57                 'tested'       => true,
    58                 'requires'     => true,
    59                 'rating'       => true,
    60                 'downloaded'   => true,
    61                 'downloadlink' => true,
    62                 'last_updated' => true,
    63                 'homepage'     => true,
    64                 'tags'         => true,
    65                 'num_ratings'  => true,
    66         );
    6753}
    6854add_action( 'after_setup_theme', 'wporg_themes_setup' );
     55
     56/**
     57 * Makes an API request to retrieve the right themes for the current query.
     58 *
     59 * @param WP_Query $query
     60 * @return WP_Query
     61 */
     62function wporg_themes_set_up_query( $query ) {
     63        if ( ! is_admin() && ! in_array( $query->query_vars['pagename'], array( 'upload', 'commercial' ) ) ) {
     64
     65                $query->set( 'post_type', 'repopackage' );
     66
     67                $args = array(
     68                        'per_page' => 15,
     69                        'fields'   => array(
     70                                'description'  => true,
     71                                'sections'     => false,
     72                                'tested'       => true,
     73                                'requires'     => true,
     74                                'rating'       => true,
     75                                'downloaded'   => true,
     76                                'downloadlink' => true,
     77                                'last_updated' => true,
     78                                'homepage'     => true,
     79                                'tags'         => true,
     80                                'num_ratings'  => true,
     81                                'parent'       => true,
     82                        ),
     83                );
     84
     85                if ( $query->query_vars['tag'] ) {
     86                        $args['tag'][] = $query->query_vars['tag'];
     87                }
     88                elseif ( $query->query_vars['author_name'] ) {
     89                        $args['author'] = $query->query_vars['author_name'];
     90                }
     91                elseif ( $query->query_vars['pagename'] ) {
     92                        $slugs = explode( '/', $query->query_vars['pagename'] );
     93
     94                        if ( count( $slugs ) > 1 && 'browse' == $slugs[0] ) {
     95                                $args['browse'] = $slugs[1];
     96                        } else {
     97                                $args['theme'] = $slugs[0];
     98                        }
     99                }
     100                else {
     101                        $args['browse'] = 'featured';
     102                }
     103
     104                if ( ! function_exists( 'themes_api' ) ) {
     105                        include ABSPATH . 'wp-admin/includes/theme.php';
     106                }
     107                $GLOBALS['themes'] = themes_api( 'query_themes', $args );
     108        }
     109
     110        return $query;
     111}
     112add_filter( 'pre_get_posts', 'wporg_themes_set_up_query' );
    69113
    70114/**
  • sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-themes/index.php

    r1151 r1156  
    1212 */
    1313
    14 include ABSPATH . 'wp-admin/includes/theme.php';
    1514
    16 $args = array(
    17         'per_page' => 15,
    18         'fields'   => array_merge( $GLOBALS['theme_field_defaults'], array(
    19                 'parent' => true,
    20         ) ),
    21 );
    22 
    23 if ( get_query_var( 'tag' ) ) {
    24         $args['tag'][] = get_query_var( 'tag' );
    25 }
    26 elseif ( get_query_var( 'author_name' ) ) {
    27         $args['author'] = get_query_var( 'author_name' );
    28 }
    29 else {
    30         $args['browse'] = 'featured';
    31 
    32         if ( in_array( get_query_var( 'name' ), array( 'featured', 'popular', 'new' ) ) ) {
    33                 $args['browse'] = get_query_var( 'name' );
    34         }
    35 }
    36 $themes = themes_api( 'query_themes', $args );
    3715
    3816get_header();
     17
     18global $themes;
    3919?>
    4020
     
    8767                                <?php
    8868                                if ( ! is_wp_error( $themes ) ) :
    89                                         foreach ( $themes->themes as $theme ) :
    90                                                 get_template_part( 'content', 'index' );
    91                                         endforeach;
     69                                        if ( is_single() ) :
     70                                                $theme = array_shift( $themes->themes );
     71                                                get_template_part( 'content', 'single' );
     72                                        else :
     73                                                foreach ( $themes->themes as $theme ) :
     74                                                        get_template_part( 'content', 'index' );
     75                                                endforeach;
     76                                        endif;
    9277                                endif;
    9378                                ?>
Note: See TracChangeset for help on using the changeset viewer.