Changeset 17952 for branches/version-2_4


Ignore:
Timestamp:
2009/04/03 11:14:09 (15 years ago)
Author:
kajiwara
Message:

#292 分対応。product用関連商品検索、追加処理部分は2.4.0RC1での改修前のファイルに戻しました。

Location:
branches/version-2_4/data
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • branches/version-2_4/data/Smarty/templates/default/admin/products/product_select.tpl

    r17773 r17952  
    4040self.moveTo(20,20);self.focus(); 
    4141 
    42 function func_submit( product_id, class_name1, class_name2 ){ 
    43     var err_text = ''; 
    44     var fm = window.opener.document.form1; 
    45     var fm1 = window.opener.document; 
    46     var class1 = "classcategory_id" + product_id + "_1"; 
    47     var class2 = "classcategory_id" + product_id + "_2"; 
    48  
    49     var class1_id = document.getElementById(class1).value; 
    50     var class2_id = document.getElementById(class2).value; 
    51  
    52     <!--{if $tpl_no != ''}--> 
    53         var opner_product_id = 'edit_product_id'; 
    54         var opner_classcategory_id1 = 'edit_classcategory_id1'; 
    55         var opner_classcategory_id2 = 'edit_classcategory_id2'; 
    56         fm1.getElementById("no").value = <!--{$tpl_no}-->; 
    57     <!--{else}--> 
    58         var opner_product_id = 'add_product_id'; 
    59         var opner_classcategory_id1 = 'add_classcategory_id1'; 
    60         var opner_classcategory_id2 = 'add_classcategory_id2'; 
    61     <!--{/if}--> 
    62  
    63     if (document.getElementById(class1).type == 'select-one' && class1_id == '') { 
    64         err_text = class_name1 + "を選択してください。\n"; 
    65     } 
    66     if (document.getElementById(class2).type == 'select-one' && class2_id == '') { 
    67         err_text = err_text + class_name2 + "を選択してください。\n"; 
    68     } 
    69     if (err_text != '') { 
    70         alert(err_text); 
    71         return false; 
    72     } 
    73  
    74     fm1.getElementById(opner_product_id).value = product_id; 
    75     if (class1_id != '') { 
    76         fm1.getElementById(opner_classcategory_id1).value = class1_id; 
    77     } 
    78     if (class2_id != '') { 
    79         fm1.getElementById(opner_classcategory_id2).value = class2_id; 
    80     } 
    81  
    82     fm.mode.value = 'select_product_detail'; 
    83     fm.anchor_key.value = 'order_products'; 
    84     fm.submit(); 
    85     window.close(); 
    86  
    87     return true; 
     42function func_submit( id ){ 
     43    var fm = window.opener.document.form1; 
     44    fm.recommend_id<!--{$smarty.get.no}-->.value = id; 
     45    fm.mode.value = 'recommend_select'; 
     46    fm.anchor_key.value = 'recommend_no<!--{$smarty.get.no}-->'; 
     47    fm.submit(); 
     48    window.close(); 
     49    return false; 
    8850} 
    8951//--> 
    9052</script> 
    91  
    92 <script type="text/javascript">//<![CDATA[ 
    93 // セレクトボックスに項目を割り当てる。 
    94 function lnSetSelect(name1, name2, id, val) { 
    95     sele1 = document.form1[name1]; 
    96     sele2 = document.form1[name2]; 
    97     lists = eval('lists' + id); 
    98     vals = eval('vals' + id); 
    99  
    100     if(sele1 && sele2) { 
    101         index = sele1.selectedIndex; 
    102  
    103         // セレクトボックスのクリア 
    104         count = sele2.options.length; 
    105         for(i = count; i >= 0; i--) { 
    106             sele2.options[i] = null; 
    107         } 
    108  
    109         // セレクトボックスに値を割り当てる 
    110         len = lists[index].length; 
    111         for(i = 0; i < len; i++) { 
    112             sele2.options[i] = new Option(lists[index][i], vals[index][i]); 
    113             if(val != "" && vals[index][i] == val) { 
    114                 sele2.options[i].selected = true; 
    115             } 
    116         } 
    117     } 
    118 } 
    119 //]]> 
    120 </script> 
    121  
    122  
    123 <script type="text/javascript">//<![CDATA[ 
    124     <!--{$tpl_javascript}--> 
    125 //]]> 
    126 </script> 
    127  
    12853<title>ECサイト管理者ページ</title> 
    12954</head> 
     
    14469<input name="search_pageno" type="hidden" value=""> 
    14570<table bgcolor="#cccccc" width="420" border="0" cellspacing="1" cellpadding="5" summary=" "> 
    146     <tr class="fs12n"> 
    147         <td bgcolor="#f0f0f0" width="100">カテゴリ</td> 
    148         <td bgcolor="#ffffff" width="287"><select name="search_category_id"> 
    149         <option value="" selected="selected">選択してください</option> 
    150         <!--{html_options options=$arrCatList selected=$arrForm.search_category_id}--> 
    151         </select> 
    152         </td> 
    153     </tr> 
    154     <tr class="fs12n"> 
    155         <td bgcolor="#f0f0f0">商品名</td> 
    156         <td bgcolor="#ffffff"><input type="text" name="search_name" value="<!--{$arrForm.search_name}-->" size="35" class="box35" /></td> 
    157     </tr> 
    158     <tr class="fs12n"> 
    159         <td bgcolor="#f0f0f0">商品番号</td> 
    160         <td bgcolor="#ffffff"><input type="text" name="search_product_code" value="<!--{$arrForm.search_product_code}-->" size="35" class="box35" /></td> 
    161     </tr> 
     71    <tr class="fs12n"> 
     72        <td bgcolor="#f0f0f0" width="100">カテゴリ</td> 
     73        <td bgcolor="#ffffff" width="287"><select name="search_category_id"> 
     74        <option value="" selected="selected">選択してください</option> 
     75        <!--{html_options options=$arrCatList selected=$arrForm.search_category_id}--> 
     76        </select> 
     77        </td> 
     78    </tr> 
     79    <tr class="fs12n"> 
     80        <td bgcolor="#f0f0f0">商品名</td> 
     81        <td bgcolor="#ffffff"><input type="text" name="search_name" value="<!--{$arrForm.search_name}-->" size="35" class="box35" /></td> 
     82    </tr> 
    16283</table> 
    16384<br /> 
     
    16687<br /> 
    16788 
    168     <!--▼検索結果表示--> 
    169     <!--{if $tpl_linemax}--> 
    170     <table width="420" border="0" cellspacing="0" cellpadding="0" summary=" " bgcolor="#FFFFFF"> 
    171         <tr class="fs12"> 
    172             <td align="left"><!--{$tpl_linemax}-->件が該当しました。 </td> 
    173         </tr> 
    174         <tr class="fs12"> 
    175             <td align="center"> 
    176             <!--▼ページナビ--> 
    177             <!--{$tpl_strnavi}--> 
    178             <!--▲ページナビ--> 
    179             </td> 
    180         </tr> 
    181         <tr><td height="10"></td></tr> 
    182     </table> 
    183  
    184     <!--▼検索後表示部分--> 
    185     <table width="420" border="0" cellspacing="1" cellpadding="5" bgcolor="#cccccc"> 
    186         <tr bgcolor="#f0f0f0" align="center" class="fs12"> 
    187             <td>商品画像</td> 
    188             <td>商品番号</td> 
    189             <td>商品名</td> 
    190             <td>決定</td> 
    191         </tr> 
    192         <!--{section name=cnt loop=$arrProducts}--> 
    193         <!--{assign var=id value=$arrProducts[cnt].product_id}--> 
    194         <!--▼商品<!--{$smarty.section.cnt.iteration}-->--> 
    195         <tr bgcolor="#FFFFFF" class="fs12n"> 
    196             <td width="90" align="center"> 
    197             <!--{if $arrProducts[cnt].main_list_image != ""}--> 
    198                 <!--{assign var=image_path value="`$arrProducts[cnt].main_list_image`"}--> 
    199             <!--{else}--> 
    200                 <!--{assign var=image_path value="`$smarty.const.NO_IMAGE_DIR`"}--> 
    201             <!--{/if}--> 
    202             <img src="<!--{$smarty.const.SITE_URL}-->resize_image.php?image=<!--{$image_path}-->&width=65&height=65" alt="<!--{$arrRecommend[$recommend_no].name|escape}-->"> 
    203             </td> 
    204             <td> 
    205             <!--{$arrProducts[cnt].name|escape}--> 
    206  
    207             <!--{assign var=codemin value=`$arrProducts[cnt].product_code_min`}--> 
    208             <!--{assign var=codemax value=`$arrProducts[cnt].product_code_max`}--> 
    209             <!--{* 商品コード *}--> 
    210                 <!--{if $codemin != $codemax}--> 
    211                     <!--{$codemin|escape}-->〜<!--{$codemax|escape}--> 
    212                 <!--{else}--> 
    213                     <!--{$codemin|escape}--> 
    214                 <!--{/if}--> 
    215             </td> 
    216             <td> 
    217                 <!--{$arrProducts[cnt].name|escape}--> 
    218  
    219                 <!--{assign var=class1 value=classcategory_id`$id`_1}--> 
    220                 <!--{assign var=class2 value=classcategory_id`$id`_2}--> 
    221                 <!--{if $tpl_classcat_find1[$id]}--> 
    222                 <dt><!--{$tpl_class_name1[$id]|escape}-->:</dt> 
    223                 <dd> 
    224                     <select name="<!--{$class1}-->" id="<!--{$class1}-->" style="<!--{$arrErr[$class1]|sfGetErrorColor}-->" onchange="lnSetSelect('<!--{$class1}-->', '<!--{$class2}-->', '<!--{$id}-->','');"> 
    225                     <option value="">選択してください</option> 
    226                     <!--{html_options options=$arrClassCat1[$id] selected=$arrForm[$class1]}--> 
    227                     </select> 
    228                     <!--{if $arrErr[$class1] != ""}--> 
    229                     <br /><span class="attention">※ <!--{$tpl_class_name1[$id]}-->を入力して下さい。</span> 
    230                     <!--{/if}--> 
    231                 </dd> 
    232                 <!--{else}--> 
    233                 <input type="hidden" name="<!--{$class1}-->" id="<!--{$class1}-->" value=""> 
    234                 <!--{/if}--> 
    235                 <!--{if $tpl_classcat_find2[$id]}--> 
    236                     <dt><!--{$tpl_class_name2[$id]|escape}-->:</dt> 
    237                     <dd> 
    238                         <select name="<!--{$class2}-->" id="<!--{$class2}-->" style="<!--{$arrErr[$class2]|sfGetErrorColor}-->"> 
    239                         <option value="">選択してください</option> 
    240                         </select> 
    241                         <!--{if $arrErr[$class2] != ""}--> 
    242                         <br /><span class="attention">※ <!--{$tpl_class_name2[$id]}-->を入力して下さい。</span> 
    243                         <!--{/if}--> 
    244                     </dd> 
    245                 <!--{else}--> 
    246                     <input type="hidden" name="<!--{$class2}-->" id="<!--{$class2}-->" value=""> 
    247                 <!--{/if}--> 
    248             </td> 
    249  
    250             <td align="center"><a href="" onclick="return func_submit('<!--{$arrProducts[cnt].product_id}-->', '<!--{$tpl_class_name1[$id]}-->', '<!--{$tpl_class_name2[$id]}-->')">決定</a></td> 
    251         </tr> 
    252         <!--▲商品<!--{$smarty.section.cnt.iteration}-->--> 
    253         <!--{sectionelse}--> 
    254         <tr bgcolor="#FFFFFF" class="fs10n"> 
    255             <td colspan="4">商品が登録されていません</td> 
    256         </tr> 
    257         <!--{/section}--> 
    258     </table> 
    259     <br /> 
    260     <br /> 
    261     <!--{/if}--> 
    262     <!--▲検索結果表示--> 
     89    <!--▼検索結果表示--> 
     90    <!--{if $tpl_linemax}--> 
     91    <table width="420" border="0" cellspacing="0" cellpadding="0" summary=" " bgcolor="#FFFFFF"> 
     92        <tr class="fs12"> 
     93            <td align="left"><!--{$tpl_linemax}-->件が該当しました。 </td> 
     94        </tr> 
     95        <tr class="fs12"> 
     96            <td align="center"> 
     97            <!--▼ページナビ--> 
     98            <!--{$tpl_strnavi}--> 
     99            <!--▲ページナビ--> 
     100            </td> 
     101        </tr> 
     102        <tr><td height="10"></td></tr> 
     103    </table> 
     104         
     105    <!--▼検索後表示部分--> 
     106    <table width="420" border="0" cellspacing="1" cellpadding="5" bgcolor="#cccccc"> 
     107        <tr bgcolor="#f0f0f0" align="center" class="fs12"> 
     108            <td>商品画像</td> 
     109            <td>商品番号</td> 
     110            <td>商品名</td> 
     111            <td>決定</td> 
     112        </tr> 
     113        <!--{section name=cnt loop=$arrProducts}--> 
     114        <!--▼商品<!--{$smarty.section.cnt.iteration}-->--> 
     115        <tr bgcolor="#FFFFFF" class="fs12n"> 
     116            <td width="90" align="center"> 
     117            <!--{if $arrProducts[cnt].main_list_image != ""}--> 
     118                <!--{assign var=image_path value="`$arrProducts[cnt].main_list_image`"}--> 
     119            <!--{else}--> 
     120                <!--{assign var=image_path value="`$smarty.const.NO_IMAGE_DIR`"}--> 
     121            <!--{/if}--> 
     122            <img src="<!--{$smarty.const.SITE_URL}-->resize_image.php?image=<!--{$image_path}-->&width=65&height=65" alt="<!--{$arrRecommend[$recommend_no].name|escape}-->"> 
     123            </td>    
     124            <td><!--{$arrProducts[cnt].product_code|escape|default:"-"}--></td> 
     125            <td><!--{$arrProducts[cnt].name|escape}--></td> 
     126            <td align="center"><a href="" onClick="return func_submit(<!--{$arrProducts[cnt].product_id}-->)">決定</a></td> 
     127        </tr> 
     128        <!--▲商品<!--{$smarty.section.cnt.iteration}-->--> 
     129        <!--{sectionelse}--> 
     130        <tr bgcolor="#FFFFFF" class="fs10n"> 
     131            <td colspan="4">商品が登録されていません</td> 
     132        </tr>    
     133        <!--{/section}--> 
     134    </table> 
     135    <br /> 
     136    <br /> 
     137    <!--{/if}--> 
     138    <!--▲検索結果表示--> 
    263139 
    264140</form> 
  • branches/version-2_4/data/class/pages/admin/products/LC_Page_Admin_Products_ProductSelect.php

    r17777 r17952  
    6262        $objSess = new SC_Session(); 
    6363        $objDb = new SC_Helper_DB_Ex(); 
    64         $objQuery = new SC_Query(); 
    6564 
    6665        // 認証可否の判定 
     
    6867 
    6968        if (!isset($_POST['mode'])) $_POST['mode'] = ""; 
    70  
    71         if ($_GET['no'] != '') { 
    72             $this->tpl_no = strval($_GET['no']); 
    73         }elseif ($_POST['no'] != '') { 
    74             $this->tpl_no = strval($_POST['no']); 
    75         } 
    7669 
    7770        if ($_POST['mode'] == "search") { 
     
    8982                    continue; 
    9083                } 
     84 
    9185                switch ($key) { 
    9286                case 'search_name': 
     
    110104            } 
    111105 
    112  
    113             /* 
    114106            $order = "update_date DESC, product_id DESC "; 
    115107 
     
    117109            $col = "product_id, name, category_id, main_list_image, status, product_code, price01, stock, stock_unlimited"; 
    118110            $from = "vw_products_nonclass AS noncls "; 
    119             */ 
    120             $col = "DISTINCT T1.product_id, product_code_min, product_code_max," 
    121                  . " price01_min, price01_max, price02_min, price02_max," 
    122                  . " stock_min, stock_max, stock_unlimited_min," 
    123                  . " stock_unlimited_max, del_flg, status, name, comment1," 
    124                  . " comment2, comment3, main_list_comment, main_image," 
    125                  . " main_list_image, product_flag, deliv_date_id, sale_limit," 
    126                  . " point_rate, sale_unlimited, create_date, deliv_fee, " 
    127                  . " T4.product_rank, T4.category_rank"; 
    128             $from = "vw_products_allclass AS T1" 
    129                   . " JOIN (" 
    130                   . " SELECT max(T3.rank) AS category_rank," 
    131                   . "        max(T2.rank) AS product_rank," 
    132                   . "        T2.product_id" 
    133                   . "   FROM dtb_product_categories T2" 
    134                   . "   JOIN dtb_category T3 USING (category_id)" 
    135                   . " GROUP BY product_id) AS T4 USING (product_id)"; 
    136             $order = "T4.category_rank DESC, T4.product_rank DESC"; 
    137111 
    138112            $objQuery = new SC_Query(); 
     
    167141            // 検索結果の取得 
    168142            $this->arrProducts = $objQuery->select($col, $from, $where, $arrval); 
    169  
    170             // 規格名一覧 
    171             $arrClassName = $objDb->sfGetIDValueList("dtb_class", "class_id", "name"); 
    172  
    173             // 規格分類名一覧 
    174             $arrClassCatName = $objDb->sfGetIDValueList("dtb_classcategory", "classcategory_id", "name"); 
    175  
    176             // 規格セレクトボックス設定 
    177             for($i = 0; $i < count($this->arrProducts); $i++) { 
    178                 $this->lfMakeSelect($this->arrProducts[$i]['product_id'], $arrClassName, $arrClassCatName); 
    179                 // 購入制限数を取得 
    180                 $this->lfGetSaleLimit($this->arrProducts[$i]); 
    181             } 
    182143        } 
    183144 
     
    219180        } 
    220181    } 
    221  
    222     /* 規格セレクトボックスの作成 */ 
    223     function lfMakeSelect($product_id, $arrClassName, $arrClassCatName) { 
    224  
    225         $classcat_find1 = false; 
    226         $classcat_find2 = false; 
    227         // 在庫ありの商品の有無 
    228         $stock_find = false; 
    229  
    230         // 商品規格情報の取得 
    231         $arrProductsClass = $this->lfGetProductsClass($product_id); 
    232  
    233         // 規格1クラス名の取得 
    234         $this->tpl_class_name1[$product_id] = 
    235             isset($arrClassName[$arrProductsClass[0]['class_id1']]) 
    236             ? $arrClassName[$arrProductsClass[0]['class_id1']] 
    237             : ""; 
    238  
    239         // 規格2クラス名の取得 
    240         $this->tpl_class_name2[$product_id] = 
    241             isset($arrClassName[$arrProductsClass[0]['class_id2']]) 
    242             ? $arrClassName[$arrProductsClass[0]['class_id2']] 
    243             : ""; 
    244  
    245         // すべての組み合わせ数 
    246         $count = count($arrProductsClass); 
    247  
    248         $classcat_id1 = ""; 
    249  
    250         $arrSele = array(); 
    251         $arrList = array(); 
    252  
    253         $list_id = 0; 
    254         $arrList[0] = "\tlist". $product_id. "_0 = new Array('選択してください'"; 
    255         $arrVal[0] = "\tval". $product_id. "_0 = new Array(''"; 
    256  
    257         for ($i = 0; $i < $count; $i++) { 
    258             // 在庫のチェック 
    259             if($arrProductsClass[$i]['stock'] <= 0 && $arrProductsClass[$i]['stock_unlimited'] != '1') { 
    260                 continue; 
    261             } 
    262  
    263             $stock_find = true; 
    264  
    265             // 規格1のセレクトボックス用 
    266             if($classcat_id1 != $arrProductsClass[$i]['classcategory_id1']){ 
    267                 $arrList[$list_id].=");\n"; 
    268                 $arrVal[$list_id].=");\n"; 
    269                 $classcat_id1 = $arrProductsClass[$i]['classcategory_id1']; 
    270                 $arrSele[$classcat_id1] = $arrClassCatName[$classcat_id1]; 
    271                 $list_id++; 
    272  
    273                 $arrList[$list_id] = ""; 
    274                 $arrVal[$list_id] = ""; 
    275             } 
    276  
    277             // 規格2のセレクトボックス用 
    278             $classcat_id2 = $arrProductsClass[$i]['classcategory_id2']; 
    279  
    280             // セレクトボックス表示値 
    281             if($arrList[$list_id] == "") { 
    282                 $arrList[$list_id] = "\tlist". $product_id. "_". $list_id. " = new Array('選択してください', '". $arrClassCatName[$classcat_id2]. "'"; 
    283             } else { 
    284                 $arrList[$list_id].= ", '".$arrClassCatName[$classcat_id2]."'"; 
    285             } 
    286  
    287             // セレクトボックスPOST値 
    288             if($arrVal[$list_id] == "") { 
    289                 $arrVal[$list_id] = "\tval". $product_id. "_". $list_id. " = new Array('', '". $classcat_id2. "'"; 
    290             } else { 
    291                 $arrVal[$list_id].= ", '".$classcat_id2."'"; 
    292             } 
    293         } 
    294  
    295         $arrList[$list_id].=");\n"; 
    296         $arrVal[$list_id].=");\n"; 
    297  
    298         // 規格1 
    299         $this->arrClassCat1[$product_id] = $arrSele; 
    300  
    301         $lists = "\tlists".$product_id. " = new Array("; 
    302         $no = 0; 
    303         foreach($arrList as $val) { 
    304             $this->tpl_javascript.= $val; 
    305             if ($no != 0) { 
    306                 $lists.= ",list". $product_id. "_". $no; 
    307             } else { 
    308                 $lists.= "list". $product_id. "_". $no; 
    309             } 
    310             $no++; 
    311         } 
    312         $this->tpl_javascript.= $lists.");\n"; 
    313  
    314         $vals = "\tvals".$product_id. " = new Array("; 
    315         $no = 0; 
    316         foreach($arrVal as $val) { 
    317             $this->tpl_javascript.= $val; 
    318             if ($no != 0) { 
    319                 $vals.= ",val". $product_id. "_". $no; 
    320             } else { 
    321                 $vals.= "val". $product_id. "_". $no; 
    322             } 
    323             $no++; 
    324         } 
    325         $this->tpl_javascript.= $vals.");\n"; 
    326  
    327         // 選択されている規格2ID 
    328         $classcategory_id = "classcategory_id". $product_id; 
    329  
    330         $classcategory_id_2 = $classcategory_id . "_2"; 
    331         if (!isset($classcategory_id_2)) $classcategory_id_2 = ""; 
    332         if (!isset($_POST[$classcategory_id_2])) $_POST[$classcategory_id_2] = ""; 
    333  
    334         $this->tpl_onload .= "lnSetSelect('" . $classcategory_id ."_1', " 
    335             . "'" . $classcategory_id_2 . "'," 
    336             . "'" . $product_id . "'," 
    337             . "'" . $_POST[$classcategory_id_2] ."'); "; 
    338  
    339         // 規格1が設定されている 
    340         if($arrProductsClass[0]['classcategory_id1'] != '0') { 
    341             $classcat_find1 = true; 
    342         } 
    343  
    344         // 規格2が設定されている 
    345         if($arrProductsClass[0]['classcategory_id2'] != '0') { 
    346             $classcat_find2 = true; 
    347         } 
    348  
    349         $this->tpl_classcat_find1[$product_id] = $classcat_find1; 
    350         $this->tpl_classcat_find2[$product_id] = $classcat_find2; 
    351         $this->tpl_stock_find[$product_id] = $stock_find; 
    352     } 
    353  
    354     /* 商品規格情報の取得 */ 
    355     function lfGetProductsClass($product_id) { 
    356         $arrRet = array(); 
    357         if(SC_Utils_Ex::sfIsInt($product_id)) { 
    358             // 商品規格取得 
    359             $objQuery = new SC_Query(); 
    360             $col = "product_class_id, classcategory_id1, classcategory_id2, class_id1, class_id2, stock, stock_unlimited"; 
    361             $table = "vw_product_class AS prdcls"; 
    362             $where = "product_id = ?"; 
    363             $objQuery->setorder("rank1 DESC, rank2 DESC"); 
    364             $arrRet = $objQuery->select($col, $table, $where, array($product_id)); 
    365         } 
    366         return $arrRet; 
    367     } 
    368  
    369     // 購入制限数の設定 
    370     function lfGetSaleLimit($product) { 
    371         //在庫が無限または購入制限値が設定値より大きい場合 
    372         if($product['sale_unlimited'] == 1 || $product['sale_limit'] > SALE_LIMIT_MAX) { 
    373             $this->tpl_sale_limit[$product['product_id']] = SALE_LIMIT_MAX; 
    374         } else { 
    375             $this->tpl_sale_limit[$product['product_id']] = $product['sale_limit']; 
    376         } 
    377     } 
    378182} 
    379183?> 
Note: See TracChangeset for help on using the changeset viewer.