changeset 1452:8585fbf3ed06 beta

Implemented #111 copy github node finder solution
author Marcin Kuzminski <marcin@python-works.com>
date Sun, 28 Aug 2011 02:17:42 +0300
parents 200e6631787e
children 55a4cbcd464d
files rhodecode/config/routing.py rhodecode/controllers/files.py rhodecode/public/css/style.css rhodecode/templates/files/files_browser.html
diffstat 4 files changed, 195 insertions(+), 18 deletions(-) [+]
line wrap: on
line diff
--- a/rhodecode/config/routing.py	Sat Aug 27 17:55:58 2011 +0300
+++ b/rhodecode/config/routing.py	Sun Aug 28 02:17:42 2011 +0300
@@ -382,6 +382,11 @@
                 controller='files', action='archivefile',
                 conditions=dict(function=check_repo))
 
+    rmap.connect('files_nodelist_home',
+                 '/{repo_name:.*}/nodelist/{revision}/{f_path:.*}',
+                controller='files', action='nodelist',
+                conditions=dict(function=check_repo))
+
     rmap.connect('repo_settings_delete', '/{repo_name:.*}/settings',
                 controller='settings', action="delete",
                 conditions=dict(method=["DELETE"], function=check_repo))
--- a/rhodecode/controllers/files.py	Sat Aug 27 17:55:58 2011 +0300
+++ b/rhodecode/controllers/files.py	Sun Aug 28 02:17:42 2011 +0300
@@ -25,12 +25,14 @@
 
 import os
 import logging
-import mimetypes
 import traceback
 
+from os.path import join as jn
+
 from pylons import request, response, session, tmpl_context as c, url
 from pylons.i18n.translation import _
 from pylons.controllers.util import redirect
+from pylons.decorators import jsonify
 
 from vcs.backends import ARCHIVE_SPECS
 from vcs.exceptions import RepositoryError, ChangesetDoesNotExistError, \
@@ -95,6 +97,26 @@
 
         return file_node
 
+
+    def __get_paths(self, changeset, starting_path):
+        """recursive walk in root dir and return a set of all path in that dir
+        based on repository walk function
+        """
+        _files = list()
+        _dirs = list()
+
+        try:
+            tip = changeset
+            for topnode, dirs, files in tip.walk(starting_path):
+                for f in files:
+                    _files.append(f.path)
+                for d in dirs:
+                    _dirs.append(d.path)
+        except RepositoryError, e:
+            log.debug(traceback.format_exc())
+            pass
+        return _dirs, _files
+
     @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
                                    'repository.admin')
     def index(self, repo_name, revision, f_path):
@@ -413,3 +435,13 @@
         hist_l.append(tags_group)
 
         return hist_l
+
+    @jsonify
+    @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
+                                   'repository.admin')
+    def nodelist(self, repo_name, revision, f_path):
+        if request.environ.get('HTTP_X_PARTIAL_XHR'):
+            cs = self.__get_cs_or_redirect(revision, repo_name)
+            _d, _f = self.__get_paths(cs, f_path)
+            return _d + _f
+
--- a/rhodecode/public/css/style.css	Sat Aug 27 17:55:58 2011 +0300
+++ b/rhodecode/public/css/style.css	Sun Aug 28 02:17:42 2011 +0300
@@ -52,7 +52,6 @@
 color:#003367;
 text-decoration:none;
 cursor:pointer;
-font-weight:700;
 }
 
 a:hover {
@@ -1863,7 +1862,7 @@
 
 div.browserblock .browser-header {
 background:#FFF;
-padding:10px 0px 25px 0px;
+padding:10px 0px 15px 0px;
 width: 100%;
 }
 div.browserblock .browser-nav {
@@ -1884,6 +1883,25 @@
 font-weight:700;
 }
 
+div.browserblock .browser-search{
+	clear:both;
+	padding:8px 8px 0px 5px;
+}
+
+div.browserblock .search_activate #filter_activate{
+	vertical-align: sub;
+	border: 1px solid;
+	padding:2px;
+	border-radius: 4px 4px 4px 4px;
+	background: url("../images/button.png") repeat-x scroll 0 0 #E5E3E3;
+	border-color: #DDDDDD #DDDDDD #C6C6C6 #C6C6C6;
+	color: #515151;
+}
+
+div.browserblock .search_activate a:hover{
+    text-decoration: none !important;    
+}
+
 div.browserblock .browser-body {
 background:#EEE;
 border-top:1px solid #CCC;
@@ -2719,3 +2737,8 @@
 padding-left:3px;
 }
 
+#node_filter{
+border:0px solid #545454;
+color:#AAAAAA;
+padding-left:3px;
+}
--- a/rhodecode/templates/files/files_browser.html	Sat Aug 27 17:55:58 2011 +0300
+++ b/rhodecode/templates/files/files_browser.html	Sun Aug 28 02:17:42 2011 +0300
@@ -12,7 +12,7 @@
 			<div class="info_box">
 	          <span class="rev">${_('view')}@rev</span> 
 	          <a class="rev" href="${c.url_prev}" title="${_('previous revision')}">&laquo;</a>
-	          ${h.text('at_rev',value=c.changeset.revision,size=3)}
+	          ${h.text('at_rev',value=c.changeset.revision,size=5)}
 	          <a class="rev" href="${c.url_next}" title="${_('next revision')}">&raquo;</a>
 	          ## ${h.submit('view',_('view'),class_="ui-button-small")}
 		    </div>           
@@ -21,20 +21,133 @@
 	    <div class="browser-branch">
 	       ${h.checkbox('stay_at_branch',c.changeset.branch,c.changeset.branch==c.branch)}
 	       <label>${_('follow current branch')}</label>
-	       <script type="text/javascript">
-	        YUE.on('stay_at_branch','click',function(e){
-	        	if(e.target.checked){
-	        		var uri = "${h.url.current(branch='__BRANCH__')}"
-	        		uri = uri.replace('__BRANCH__',e.target.value);
-	        		window.location = uri;
-	        	}
-	        	else{
-	        		window.location = "${h.url.current()}";
-	        	}
-	        	
-	        })
-	       </script>
 	    </div>
+        <div class="browser-search">
+            <div class="search_activate">
+                <a id="filter_activate" href="#">${_('search file list')}</a>
+            </div>
+        
+            
+        <div>
+            <div id="node_filter_box_loading" style="display:none">${_('Loading file list...')}</div>
+            <div id="node_filter_box" style="display:none">
+            ${h.files_breadcrumbs(c.repo_name,c.changeset.raw_id,c.files_list.path)}/<input type="text" value="type to search..." name="filter" size="25" id="node_filter" autocomplete="off">
+            
+            <script type="text/javascript">
+            
+            YUE.on('stay_at_branch','click',function(e){
+                if(e.target.checked){
+                    var uri = "${h.url.current(branch='__BRANCH__')}"
+                    uri = uri.replace('__BRANCH__',e.target.value);
+                    window.location = uri;
+                }
+                else{
+                    window.location = "${h.url.current()}";
+                }
+                
+            })            
+            
+            var n_filter = YUD.get('node_filter');
+            var F = YAHOO.namespace('node_filter');
+            
+            var url = '${h.url("files_nodelist_home",repo_name="__REPO__",revision="__REVISION__",f_path="__FPATH__")}';
+            var node_url = '${h.url("files_home",repo_name="__REPO__",revision="__REVISION__",f_path="__FPATH__")}';
+            
+            url  = url.replace('__REPO__','${c.repo_name}');
+            url  = url.replace('__REVISION__','${c.changeset.raw_id}');
+            url  = url.replace('__FPATH__','${c.files_list.path}');
+
+            node_url  = node_url.replace('__REPO__','${c.repo_name}');
+            node_url  = node_url.replace('__REVISION__','${c.changeset.raw_id}');
+            
+            
+            F.filterTimeout = null;
+            var nodes = null;
+            
+            
+            F.initFilter = function(){
+              YUD.setStyle('node_filter_box_loading','display','');
+              YUD.setStyle('filter_activate','display','none');
+              YUC.initHeader('X-PARTIAL-XHR',true);
+              YUC.asyncRequest('GET',url,{
+                  success:function(o){
+                  	nodes = JSON.parse(o.responseText);
+                  	YUD.setStyle('node_filter_box_loading','display','none');
+                  	YUD.setStyle('node_filter_box','display','');
+                  },
+                  failure:function(o){
+                      console.log('failed to load');
+                  }
+              },null);            
+            }
+            
+            F.updateFilter  = function(e) {
+            	
+            	return function(){
+                    // Reset timeout 
+                    F.filterTimeout = null;
+                    var query = e.target.value;
+                    var match = [];
+                    var matches = 0;
+                    var matches_max = 20;
+                    if (query != ""){
+                        for(var i=0;i<nodes.length;i++){
+                            var pos = nodes[i].toLowerCase().indexOf(query)
+                            if(query && pos != -1){
+                                
+                                matches++
+                                //show only certain amount to not kill browser 
+                                if (matches > matches_max){
+                                    break;
+                                }
+                                
+                                var n = nodes[i];
+                                var n_hl = n.substring(0,pos)
+                                  +"<b>{0}</b>".format(n.substring(pos,pos+query.length))
+                                  +n.substring(pos+query.length)                    
+                                match.push('<tr><td><a class="browser-file" href="{0}">{1}</a></td><td colspan="5"></td></tr>'.format(node_url.replace('__FPATH__',n),n_hl));
+                            }
+                            if(match.length >= matches_max){
+                                match.push('<tr><td>{0}</td><td colspan="5"></td></tr>'.format("${_('search truncated')}"));
+                            }
+                            
+                        }                    	
+                    }
+                    
+                    if(query != ""){
+                        YUD.setStyle('tbody','display','none');
+                        YUD.setStyle('tbody_filtered','display','');
+                        
+                        if (match.length==0){
+                          match.push('<tr><td>{0}</td><td colspan="5"></td></tr>'.format("${_('no matching files')}"));
+                        }                        	
+                        
+                    	YUD.get('tbody_filtered').innerHTML = match.join("");	
+                    }
+                    else{
+                    	YUD.setStyle('tbody','display','');
+                    	YUD.setStyle('tbody_filtered','display','none');
+                    }
+                    
+            	}
+            }
+            
+            
+            YUE.on(YUD.get('filter_activate'),'click',function(){
+                F.initFilter();
+            })
+            YUE.on(n_filter,'click',function(){
+                n_filter.value = '';
+             });
+            YUE.on(n_filter,'keyup',function(e){
+                clearTimeout(F.filterTimeout); 
+                F.filterTimeout = setTimeout(F.updateFilter(e),600);
+            });            
+            </script>
+            
+            </div>        
+        </div>
+        </div>      
     </div>
     
 	<div class="browser-body">
@@ -49,7 +162,8 @@
 		                 <th>${_('Last commiter')}</th>
 		             </tr>
 		         </thead>
-
+                
+                <tbody id="tbody">
           		%if c.files_list.parent:
          		<tr class="parity0">
 	          		<td>		          		
@@ -97,6 +211,9 @@
 		             </td>
 				</tr>
 			%endfor
+                </tbody>
+                <tbody id="tbody_filtered" style="display:none">
+                </tbody>                
 		</table>
 	</div>
 </div>
\ No newline at end of file