Show More
@@ -0,0 +1,25 b'' | |||||
|
1 | <dl> | |||
|
2 | <dt class="file_history">${_('History')}</dt> | |||
|
3 | <dd> | |||
|
4 | <div> | |||
|
5 | <div style="float:left"> | |||
|
6 | ${h.form(h.url('files_diff_home',repo_name=c.repo_name,f_path=c.f_path),method='get')} | |||
|
7 | ${h.hidden('diff2',c.file_changeset.raw_id)} | |||
|
8 | ${h.select('diff1',c.file_changeset.raw_id,c.file_history)} | |||
|
9 | ${h.submit('diff',_('diff to revision'),class_="ui-btn")} | |||
|
10 | ${h.submit('show_rev',_('show at revision'),class_="ui-btn")} | |||
|
11 | ${h.hidden('annotate', c.annotate)} | |||
|
12 | ${h.end_form()} | |||
|
13 | </div> | |||
|
14 | <div class="file_author"> | |||
|
15 | <div class="item">${h.literal(ungettext(u'%s author',u'%s authors',len(c.authors)) % ('<b>%s</b>' % len(c.authors))) }</div> | |||
|
16 | %for email, user in c.authors: | |||
|
17 | <div class="contributor tooltip" style="float:left" title="${h.tooltip(user)}"> | |||
|
18 | <div class="gravatar" style="margin:1px"><img alt="gravatar" src="${h.gravatar_url(email, 20)}"/> </div> | |||
|
19 | </div> | |||
|
20 | %endfor | |||
|
21 | </div> | |||
|
22 | </div> | |||
|
23 | <div style="clear:both"></div> | |||
|
24 | </dd> | |||
|
25 | </dl> No newline at end of file |
@@ -534,6 +534,11 b' def make_map(config):' | |||||
534 | controller='files', revision='tip', f_path='', |
|
534 | controller='files', revision='tip', f_path='', | |
535 | conditions=dict(function=check_repo)) |
|
535 | conditions=dict(function=check_repo)) | |
536 |
|
536 | |||
|
537 | rmap.connect('files_history_home', | |||
|
538 | '/{repo_name:.*?}/history/{revision}/{f_path:.*}', | |||
|
539 | controller='files', action='history', revision='tip', f_path='', | |||
|
540 | conditions=dict(function=check_repo)) | |||
|
541 | ||||
537 | rmap.connect('files_diff_home', '/{repo_name:.*?}/diff/{f_path:.*}', |
|
542 | rmap.connect('files_diff_home', '/{repo_name:.*?}/diff/{f_path:.*}', | |
538 | controller='files', action='diff', revision='tip', f_path='', |
|
543 | controller='files', action='diff', revision='tip', f_path='', | |
539 | conditions=dict(function=check_repo)) |
|
544 | conditions=dict(function=check_repo)) |
@@ -155,12 +155,16 b' class FilesController(BaseRepoController' | |||||
155 | c.file = c.changeset.get_node(f_path) |
|
155 | c.file = c.changeset.get_node(f_path) | |
156 |
|
156 | |||
157 | if c.file.is_file(): |
|
157 | if c.file.is_file(): | |
158 | c.file_history, _hist = self._get_node_history(c.changeset, f_path) |
|
158 | c.load_full_history = False | |
159 |
|
|
159 | file_last_cs = c.file.last_changeset | |
160 | if _hist: |
|
160 | c.file_changeset = (c.changeset | |
161 | c.file_changeset = (c.changeset |
|
161 | if c.changeset.revision < file_last_cs.revision | |
162 |
|
|
162 | else file_last_cs) | |
163 | else _hist[0]) |
|
163 | _hist = [] | |
|
164 | c.file_history = [] | |||
|
165 | if c.load_full_history: | |||
|
166 | c.file_history, _hist = self._get_node_history(c.changeset, f_path) | |||
|
167 | ||||
164 | c.authors = [] |
|
168 | c.authors = [] | |
165 | for a in set([x.author for x in _hist]): |
|
169 | for a in set([x.author for x in _hist]): | |
166 | c.authors.append((h.email(a), h.person(a))) |
|
170 | c.authors.append((h.email(a), h.person(a))) | |
@@ -176,6 +180,23 b' class FilesController(BaseRepoController' | |||||
176 |
|
180 | |||
177 | return render('files/files.html') |
|
181 | return render('files/files.html') | |
178 |
|
182 | |||
|
183 | def history(self, repo_name, revision, f_path, annotate=False): | |||
|
184 | if request.environ.get('HTTP_X_PARTIAL_XHR'): | |||
|
185 | c.changeset = self.__get_cs_or_redirect(revision, repo_name) | |||
|
186 | c.f_path = f_path | |||
|
187 | c.annotate = annotate | |||
|
188 | c.file = c.changeset.get_node(f_path) | |||
|
189 | if c.file.is_file(): | |||
|
190 | file_last_cs = c.file.last_changeset | |||
|
191 | c.file_changeset = (c.changeset | |||
|
192 | if c.changeset.revision < file_last_cs.revision | |||
|
193 | else file_last_cs) | |||
|
194 | c.file_history, _hist = self._get_node_history(c.changeset, f_path) | |||
|
195 | c.authors = [] | |||
|
196 | for a in set([x.author for x in _hist]): | |||
|
197 | c.authors.append((h.email(a), h.person(a))) | |||
|
198 | return render('files/files_history_box.html') | |||
|
199 | ||||
179 | @LoginRequired() |
|
200 | @LoginRequired() | |
180 | @HasRepoPermissionAnyDecorator('repository.read', 'repository.write', |
|
201 | @HasRepoPermissionAnyDecorator('repository.read', 'repository.write', | |
181 | 'repository.admin') |
|
202 | 'repository.admin') | |
@@ -530,6 +551,8 b' class FilesController(BaseRepoController' | |||||
530 | :param changesets: if passed don't calculate history and take |
|
551 | :param changesets: if passed don't calculate history and take | |
531 | changesets defined in this list |
|
552 | changesets defined in this list | |
532 | """ |
|
553 | """ | |
|
554 | import time | |||
|
555 | s = time.time() | |||
533 | # calculate history based on tip |
|
556 | # calculate history based on tip | |
534 | tip_cs = c.rhodecode_repo.get_changeset() |
|
557 | tip_cs = c.rhodecode_repo.get_changeset() | |
535 | if changesets is None: |
|
558 | if changesets is None: | |
@@ -538,7 +561,7 b' class FilesController(BaseRepoController' | |||||
538 | except (NodeDoesNotExistError, ChangesetError): |
|
561 | except (NodeDoesNotExistError, ChangesetError): | |
539 | #this node is not present at tip ! |
|
562 | #this node is not present at tip ! | |
540 | changesets = cs.get_file_history(f_path) |
|
563 | changesets = cs.get_file_history(f_path) | |
541 |
|
564 | print time.time()-s | ||
542 | hist_l = [] |
|
565 | hist_l = [] | |
543 |
|
566 | |||
544 | changesets_group = ([], _("Changesets")) |
|
567 | changesets_group = ([], _("Changesets")) | |
@@ -546,10 +569,11 b' class FilesController(BaseRepoController' | |||||
546 | tags_group = ([], _("Tags")) |
|
569 | tags_group = ([], _("Tags")) | |
547 | _hg = cs.repository.alias == 'hg' |
|
570 | _hg = cs.repository.alias == 'hg' | |
548 | for chs in changesets: |
|
571 | for chs in changesets: | |
549 | _branch = '(%s)' % chs.branch if _hg else '' |
|
572 | #_branch = '(%s)' % chs.branch if _hg else '' | |
|
573 | _branch = chs.branch | |||
550 | n_desc = 'r%s:%s %s' % (chs.revision, chs.short_id, _branch) |
|
574 | n_desc = 'r%s:%s %s' % (chs.revision, chs.short_id, _branch) | |
551 | changesets_group[0].append((chs.raw_id, n_desc,)) |
|
575 | changesets_group[0].append((chs.raw_id, n_desc,)) | |
552 |
|
576 | print time.time()-s | ||
553 | hist_l.append(changesets_group) |
|
577 | hist_l.append(changesets_group) | |
554 |
|
578 | |||
555 | for name, chs in c.rhodecode_repo.branches.items(): |
|
579 | for name, chs in c.rhodecode_repo.branches.items(): | |
@@ -559,7 +583,7 b' class FilesController(BaseRepoController' | |||||
559 | for name, chs in c.rhodecode_repo.tags.items(): |
|
583 | for name, chs in c.rhodecode_repo.tags.items(): | |
560 | tags_group[0].append((chs, name),) |
|
584 | tags_group[0].append((chs, name),) | |
561 | hist_l.append(tags_group) |
|
585 | hist_l.append(tags_group) | |
562 |
|
586 | print time.time()-s | ||
563 | return hist_l, changesets |
|
587 | return hist_l, changesets | |
564 |
|
588 | |||
565 | @LoginRequired() |
|
589 | @LoginRequired() |
@@ -951,54 +951,53 b' var getIdentNode = function(n){' | |||||
951 | } |
|
951 | } | |
952 | }; |
|
952 | }; | |
953 |
|
953 | |||
954 |
var getSelectionLink = function( |
|
954 | var getSelectionLink = function(e) { | |
955 | return function(){ |
|
955 | ||
956 |
|
|
956 | //get selection from start/to nodes | |
957 |
|
|
957 | if (typeof window.getSelection != "undefined") { | |
958 |
|
|
958 | s = window.getSelection(); | |
959 |
|
959 | |||
960 |
|
|
960 | from = getIdentNode(s.anchorNode); | |
961 |
|
|
961 | till = getIdentNode(s.focusNode); | |
962 |
|
962 | |||
963 |
|
|
963 | f_int = parseInt(from.id.replace('L','')); | |
964 |
|
|
964 | t_int = parseInt(till.id.replace('L','')); | |
965 |
|
|
965 | ||
966 |
|
|
966 | if (f_int > t_int){ | |
967 |
|
|
967 | //highlight from bottom | |
968 |
|
|
968 | offset = -35; | |
969 |
|
|
969 | ranges = [t_int,f_int]; | |
970 |
|
|
970 | ||
|
971 | } | |||
|
972 | else{ | |||
|
973 | //highligth from top | |||
|
974 | offset = 35; | |||
|
975 | ranges = [f_int,t_int]; | |||
|
976 | } | |||
|
977 | ||||
|
978 | if (ranges[0] != ranges[1]){ | |||
|
979 | if(YUD.get('linktt') == null){ | |||
|
980 | hl_div = document.createElement('div'); | |||
|
981 | hl_div.id = 'linktt'; | |||
971 | } |
|
982 | } | |
972 | else{ |
|
983 | anchor = '#L'+ranges[0]+'-'+ranges[1]; | |
973 | //highligth from top |
|
984 | hl_div.innerHTML = ''; | |
974 | offset = 35; |
|
985 | l = document.createElement('a'); | |
975 | ranges = [f_int,t_int]; |
|
986 | l.href = location.href.substring(0,location.href.indexOf('#'))+anchor; | |
976 | } |
|
987 | l.innerHTML = _TM['Selection link']; | |
|
988 | hl_div.appendChild(l); | |||
977 |
|
989 | |||
978 | if (ranges[0] != ranges[1]){ |
|
990 | YUD.get('body').appendChild(hl_div); | |
979 | if(YUD.get('linktt') == null){ |
|
991 | ||
980 | hl_div = document.createElement('div'); |
|
992 | xy = YUD.getXY(till.id); | |
981 | hl_div.id = 'linktt'; |
|
993 | ||
982 | } |
|
994 | YUD.addClass('linktt','yui-tt'); | |
983 | anchor = '#L'+ranges[0]+'-'+ranges[1]; |
|
995 | YUD.setStyle('linktt','top',xy[1]+offset+'px'); | |
984 | hl_div.innerHTML = ''; |
|
996 | YUD.setStyle('linktt','left',xy[0]+'px'); | |
985 | l = document.createElement('a'); |
|
997 | YUD.setStyle('linktt','visibility','visible'); | |
986 | l.href = location.href.substring(0,location.href.indexOf('#'))+anchor; |
|
998 | } | |
987 | l.innerHTML = selection_link_label; |
|
999 | else{ | |
988 | hl_div.appendChild(l); |
|
1000 | YUD.setStyle('linktt','visibility','hidden'); | |
989 |
|
||||
990 | YUD.get('body').appendChild(hl_div); |
|
|||
991 |
|
||||
992 | xy = YUD.getXY(till.id); |
|
|||
993 |
|
||||
994 | YUD.addClass('linktt','yui-tt'); |
|
|||
995 | YUD.setStyle('linktt','top',xy[1]+offset+'px'); |
|
|||
996 | YUD.setStyle('linktt','left',xy[0]+'px'); |
|
|||
997 | YUD.setStyle('linktt','visibility','visible'); |
|
|||
998 | } |
|
|||
999 | else{ |
|
|||
1000 | YUD.setStyle('linktt','visibility','hidden'); |
|
|||
1001 | } |
|
|||
1002 | } |
|
1001 | } | |
1003 | } |
|
1002 | } | |
1004 | }; |
|
1003 | }; |
@@ -50,6 +50,7 b'' | |||||
50 | 'Open new pull request': "${_('Open new pull request')}", |
|
50 | 'Open new pull request': "${_('Open new pull request')}", | |
51 | 'Open new pull request for selected changesets': "${_('Open new pull request for selected changesets')}", |
|
51 | 'Open new pull request for selected changesets': "${_('Open new pull request for selected changesets')}", | |
52 | 'Show selected changes __S -> __E': "${_('Show selected changes __S -> __E')}", |
|
52 | 'Show selected changes __S -> __E': "${_('Show selected changes __S -> __E')}", | |
|
53 | 'Selection link': "${_('Selection link')}", | |||
53 | }; |
|
54 | }; | |
54 | var _TM = TRANSLATION_MAP; |
|
55 | var _TM = TRANSLATION_MAP; | |
55 | </script> |
|
56 | </script> |
@@ -39,11 +39,13 b'' | |||||
39 |
|
39 | |||
40 | <script type="text/javascript"> |
|
40 | <script type="text/javascript"> | |
41 | var CACHE = {}; |
|
41 | var CACHE = {}; | |
42 | var CACHE_EXPIRE = 60*1000; //cache for 60s |
|
42 | var CACHE_EXPIRE = 5*60*1000; //cache for 5*60s | |
43 | //used to construct links from the search list |
|
43 | //used to construct links from the search list | |
44 | var url_base = '${h.url("files_home",repo_name=c.repo_name,revision='__REV__',f_path='__FPATH__')}'; |
|
44 | var url_base = '${h.url("files_home",repo_name=c.repo_name,revision='__REV__',f_path='__FPATH__')}'; | |
45 | //send the nodelist request to this url |
|
45 | //send the nodelist request to this url | |
46 | var node_list_url = '${h.url("files_nodelist_home",repo_name=c.repo_name,revision='__REV__',f_path='__FPATH__')}'; |
|
46 | var node_list_url = '${h.url("files_nodelist_home",repo_name=c.repo_name,revision='__REV__',f_path='__FPATH__')}'; | |
|
47 | // send the node history requst to this url | |||
|
48 | var node_history_url = '${h.url("files_history_home",repo_name=c.repo_name,revision='__REV__',f_path='__FPATH__')}'; | |||
47 |
|
49 | |||
48 | var ypjax_links = function(){ |
|
50 | var ypjax_links = function(){ | |
49 | YUE.on(YUQ('.ypjax-link'), 'click',function(e){ |
|
51 | YUE.on(YUQ('.ypjax-link'), 'click',function(e){ | |
@@ -76,7 +78,7 b' var ypjax_links = function(){' | |||||
76 |
|
78 | |||
77 | // Change our States and save some data for handling events |
|
79 | // Change our States and save some data for handling events | |
78 | var data = {url:url,title:title, url_base:_url_base, |
|
80 | var data = {url:url,title:title, url_base:_url_base, | |
79 | node_list_url:_node_list_url}; |
|
81 | node_list_url:_node_list_url, rev:rev, f_path:f_path}; | |
80 | History.pushState(data, title, url); |
|
82 | History.pushState(data, title, url); | |
81 |
|
83 | |||
82 | //now we're sure that we can do ypjax things |
|
84 | //now we're sure that we can do ypjax things | |
@@ -89,8 +91,19 b' var callbacks = function(State){' | |||||
89 | ypjax_links(); |
|
91 | ypjax_links(); | |
90 | tooltip_activate(); |
|
92 | tooltip_activate(); | |
91 | fileBrowserListeners(State.url, State.data.node_list_url, State.data.url_base); |
|
93 | fileBrowserListeners(State.url, State.data.node_list_url, State.data.url_base); | |
92 | YUE.on('hlcode','mouseup',getSelectionLink("${_('Selection link')}")); |
|
94 | ||
93 |
|
95 | if(YUD.get('hlcode')){ | ||
|
96 | YUE.on('hlcode', 'mouseup', getSelectionLink); | |||
|
97 | } | |||
|
98 | //console.log(State); | |||
|
99 | if(YUD.get('load_node_history')){ | |||
|
100 | //remove all listeners due to problems of history state | |||
|
101 | YUE.removeListener('load_node_history', 'click'); | |||
|
102 | YUE.on('load_node_history', 'click', function(e){ | |||
|
103 | var _url = node_history_url.replace('__REV__',State.data.rev).replace('__FPATH__', State.data.f_path); | |||
|
104 | ypjax(_url, 'node_history', function(o){}) | |||
|
105 | }); | |||
|
106 | } | |||
94 | // Inform Google Analytics of the change |
|
107 | // Inform Google Analytics of the change | |
95 | if ( typeof window.pageTracker !== 'undefined' ) { |
|
108 | if ( typeof window.pageTracker !== 'undefined' ) { | |
96 | window.pageTracker._trackPageview(State.url); |
|
109 | window.pageTracker._trackPageview(State.url); | |
@@ -133,7 +146,9 b' YUE.onDOMReady(function(){' | |||||
133 | url: "${h.url.current()}", |
|
146 | url: "${h.url.current()}", | |
134 | data: { |
|
147 | data: { | |
135 | node_list_url: node_list_url.replace('__REV__',"${c.changeset.raw_id}").replace('__FPATH__', "${h.safe_unicode(c.file.path)}"), |
|
148 | node_list_url: node_list_url.replace('__REV__',"${c.changeset.raw_id}").replace('__FPATH__', "${h.safe_unicode(c.file.path)}"), | |
136 | url_base: url_base.replace('__REV__',"${c.changeset.raw_id}") |
|
149 | url_base: url_base.replace('__REV__',"${c.changeset.raw_id}"), | |
|
150 | rev:"${c.changeset.raw_id}", | |||
|
151 | f_path: "${h.safe_unicode(c.file.path)}" | |||
137 | } |
|
152 | } | |
138 | } |
|
153 | } | |
139 | fileBrowserListeners(_State.url, _State.data.node_list_url, _State.data.url_base); |
|
154 | fileBrowserListeners(_State.url, _State.data.node_list_url, _State.data.url_base); |
@@ -1,29 +1,13 b'' | |||||
1 | <dl> |
|
1 | <div id="node_history"> | |
2 | <dt class="file_history">${_('History')}</dt> |
|
2 | %if c.load_full_history: | |
3 | <dd> |
|
3 | <%include file='files_history_box.html'/> | |
4 | <div> |
|
4 | %else: | |
5 |
|
|
5 | <div style="padding-bottom:10px"> | |
6 | ${h.form(h.url('files_diff_home',repo_name=c.repo_name,f_path=c.f_path),method='get')} |
|
6 | <span id="load_node_history" class="ui-btn">${_('Load file history')}</span> | |
7 | ${h.hidden('diff2',c.file_changeset.raw_id)} |
|
7 | </div> | |
8 | ${h.select('diff1',c.file_changeset.raw_id,c.file_history)} |
|
8 | %endif | |
9 | ${h.submit('diff',_('diff to revision'),class_="ui-btn")} |
|
9 | </div> | |
10 | ${h.submit('show_rev',_('show at revision'),class_="ui-btn")} |
|
|||
11 | ${h.hidden('annotate', c.annotate)} |
|
|||
12 | ${h.end_form()} |
|
|||
13 | </div> |
|
|||
14 | <div class="file_author"> |
|
|||
15 | <div class="item">${h.literal(ungettext(u'%s author',u'%s authors',len(c.authors)) % ('<b>%s</b>' % len(c.authors))) }</div> |
|
|||
16 | %for email, user in c.authors: |
|
|||
17 | <div class="contributor tooltip" style="float:left" title="${h.tooltip(user)}"> |
|
|||
18 | <div class="gravatar" style="margin:1px"><img alt="gravatar" src="${h.gravatar_url(email, 20)}"/> </div> |
|
|||
19 | </div> |
|
|||
20 | %endfor |
|
|||
21 | </div> |
|
|||
22 | </div> |
|
|||
23 | <div style="clear:both"></div> |
|
|||
24 | </dd> |
|
|||
25 |
|
10 | |||
26 | </dl> |
|
|||
27 |
|
11 | |||
28 | <div id="body" class="codeblock"> |
|
12 | <div id="body" class="codeblock"> | |
29 | <div class="code-header"> |
|
13 | <div class="code-header"> | |
@@ -113,6 +97,15 b' YUE.onDOMReady(function(){' | |||||
113 |
|
97 | |||
114 | } |
|
98 | } | |
115 |
|
99 | |||
116 | YUE.on('hlcode','mouseup',getSelectionLink("${_('Selection link')}")) |
|
100 | // select code link event | |
|
101 | YUE.on('hlcode', 'mouseup', getSelectionLink); | |||
|
102 | ||||
|
103 | //load history of file | |||
|
104 | YUE.on('load_node_history', 'click', function(e){ | |||
|
105 | var _url = node_history_url.replace('__REV__','${c.file_changeset.raw_id}').replace('__FPATH__', '${c.f_path}'); | |||
|
106 | ypjax(_url, 'node_history', function(o){}) | |||
|
107 | }); | |||
|
108 | ||||
117 | }); |
|
109 | }); | |
|
110 | ||||
118 | </script> |
|
111 | </script> |
General Comments 0
You need to be logged in to leave comments.
Login now