##// END OF EJS Templates
files: bring back ability to specify numeric commit number in files selector
marcink -
r3667:a0a98ffc new-ui
parent child Browse files
Show More
@@ -1,393 +1,392 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 3 # Copyright (C) 2011-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
7 7 # (only), as published by the Free Software Foundation.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU Affero General Public License
15 15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 16 #
17 17 # This program is dual-licensed. If you wish to learn more about the
18 18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20 20
21 21 import logging
22 22 import string
23 23 import rhodecode
24 24
25 25 from pyramid.view import view_config
26 26
27 27 from rhodecode.lib.view_utils import get_format_ref_id
28 28 from rhodecode.apps._base import RepoAppView
29 29 from rhodecode.config.conf import (LANGUAGES_EXTENSIONS_MAP)
30 30 from rhodecode.lib import helpers as h, rc_cache
31 31 from rhodecode.lib.utils2 import safe_str, safe_int
32 32 from rhodecode.lib.auth import LoginRequired, HasRepoPermissionAnyDecorator
33 33 from rhodecode.lib.markup_renderer import MarkupRenderer, relative_links
34 34 from rhodecode.lib.ext_json import json
35 35 from rhodecode.lib.vcs.backends.base import EmptyCommit
36 36 from rhodecode.lib.vcs.exceptions import (
37 37 CommitError, EmptyRepositoryError, CommitDoesNotExistError)
38 38 from rhodecode.model.db import Statistics, CacheKey, User
39 39 from rhodecode.model.meta import Session
40 40 from rhodecode.model.repo import ReadmeFinder
41 41 from rhodecode.model.scm import ScmModel
42 42
43 43 log = logging.getLogger(__name__)
44 44
45 45
46 46 class RepoSummaryView(RepoAppView):
47 47
48 48 def load_default_context(self):
49 49 c = self._get_local_tmpl_context(include_app_defaults=True)
50 50 c.rhodecode_repo = None
51 51 if not c.repository_requirements_missing:
52 52 c.rhodecode_repo = self.rhodecode_vcs_repo
53 53 return c
54 54
55 55 def _get_readme_data(self, db_repo, renderer_type):
56 56
57 57 log.debug('Looking for README file')
58 58
59 59 cache_namespace_uid = 'cache_repo_instance.{}_{}'.format(
60 60 db_repo.repo_id, CacheKey.CACHE_TYPE_README)
61 61 invalidation_namespace = CacheKey.REPO_INVALIDATION_NAMESPACE.format(
62 62 repo_id=self.db_repo.repo_id)
63 63 region = rc_cache.get_or_create_region('cache_repo_longterm', cache_namespace_uid)
64 64
65 65 @region.conditional_cache_on_arguments(namespace=cache_namespace_uid)
66 66 def generate_repo_readme(repo_id, _repo_name, _renderer_type):
67 67 readme_data = None
68 68 readme_node = None
69 69 readme_filename = None
70 70 commit = self._get_landing_commit_or_none(db_repo)
71 71 if commit:
72 72 log.debug("Searching for a README file.")
73 73 readme_node = ReadmeFinder(_renderer_type).search(commit)
74 74 if readme_node:
75 75 relative_urls = {
76 76 'raw': h.route_path(
77 77 'repo_file_raw', repo_name=_repo_name,
78 78 commit_id=commit.raw_id, f_path=readme_node.path),
79 79 'standard': h.route_path(
80 80 'repo_files', repo_name=_repo_name,
81 81 commit_id=commit.raw_id, f_path=readme_node.path),
82 82 }
83 83 readme_data = self._render_readme_or_none(
84 84 commit, readme_node, relative_urls)
85 85 readme_filename = readme_node.path
86 86 return readme_data, readme_filename
87 87
88 88 inv_context_manager = rc_cache.InvalidationContext(
89 89 uid=cache_namespace_uid, invalidation_namespace=invalidation_namespace)
90 90 with inv_context_manager as invalidation_context:
91 91 args = (db_repo.repo_id, db_repo.repo_name, renderer_type,)
92 92 # re-compute and store cache if we get invalidate signal
93 93 if invalidation_context.should_invalidate():
94 94 instance = generate_repo_readme.refresh(*args)
95 95 else:
96 96 instance = generate_repo_readme(*args)
97 97
98 98 log.debug(
99 99 'Repo readme generated and computed in %.3fs',
100 100 inv_context_manager.compute_time)
101 101 return instance
102 102
103 103 def _get_landing_commit_or_none(self, db_repo):
104 104 log.debug("Getting the landing commit.")
105 105 try:
106 106 commit = db_repo.get_landing_commit()
107 107 if not isinstance(commit, EmptyCommit):
108 108 return commit
109 109 else:
110 110 log.debug("Repository is empty, no README to render.")
111 111 except CommitError:
112 112 log.exception(
113 113 "Problem getting commit when trying to render the README.")
114 114
115 115 def _render_readme_or_none(self, commit, readme_node, relative_urls):
116 116 log.debug(
117 117 'Found README file `%s` rendering...', readme_node.path)
118 118 renderer = MarkupRenderer()
119 119 try:
120 120 html_source = renderer.render(
121 121 readme_node.content, filename=readme_node.path)
122 122 if relative_urls:
123 123 return relative_links(html_source, relative_urls)
124 124 return html_source
125 125 except Exception:
126 126 log.exception(
127 127 "Exception while trying to render the README")
128 128
129 129 def _load_commits_context(self, c):
130 130 p = safe_int(self.request.GET.get('page'), 1)
131 131 size = safe_int(self.request.GET.get('size'), 10)
132 132
133 133 def url_generator(**kw):
134 134 query_params = {
135 135 'size': size
136 136 }
137 137 query_params.update(kw)
138 138 return h.route_path(
139 139 'repo_summary_commits',
140 140 repo_name=c.rhodecode_db_repo.repo_name, _query=query_params)
141 141
142 142 pre_load = ['author', 'branch', 'date', 'message']
143 143 try:
144 144 collection = self.rhodecode_vcs_repo.get_commits(
145 145 pre_load=pre_load, translate_tags=False)
146 146 except EmptyRepositoryError:
147 147 collection = self.rhodecode_vcs_repo
148 148
149 149 c.repo_commits = h.RepoPage(
150 150 collection, page=p, items_per_page=size, url=url_generator)
151 151 page_ids = [x.raw_id for x in c.repo_commits]
152 152 c.comments = self.db_repo.get_comments(page_ids)
153 153 c.statuses = self.db_repo.statuses(page_ids)
154 154
155 155 def _prepare_and_set_clone_url(self, c):
156 156 username = ''
157 157 if self._rhodecode_user.username != User.DEFAULT_USER:
158 158 username = safe_str(self._rhodecode_user.username)
159 159
160 160 _def_clone_uri = _def_clone_uri_id = c.clone_uri_tmpl
161 161 _def_clone_uri_ssh = c.clone_uri_ssh_tmpl
162 162
163 163 if '{repo}' in _def_clone_uri:
164 164 _def_clone_uri_id = _def_clone_uri.replace('{repo}', '_{repoid}')
165 165 elif '{repoid}' in _def_clone_uri:
166 166 _def_clone_uri_id = _def_clone_uri.replace('_{repoid}', '{repo}')
167 167
168 168 c.clone_repo_url = self.db_repo.clone_url(
169 169 user=username, uri_tmpl=_def_clone_uri)
170 170 c.clone_repo_url_id = self.db_repo.clone_url(
171 171 user=username, uri_tmpl=_def_clone_uri_id)
172 172 c.clone_repo_url_ssh = self.db_repo.clone_url(
173 173 uri_tmpl=_def_clone_uri_ssh, ssh=True)
174 174
175 175 @LoginRequired()
176 176 @HasRepoPermissionAnyDecorator(
177 177 'repository.read', 'repository.write', 'repository.admin')
178 178 @view_config(
179 179 route_name='repo_summary_commits', request_method='GET',
180 180 renderer='rhodecode:templates/summary/summary_commits.mako')
181 181 def summary_commits(self):
182 182 c = self.load_default_context()
183 183 self._prepare_and_set_clone_url(c)
184 184 self._load_commits_context(c)
185 185 return self._get_template_context(c)
186 186
187 187 @LoginRequired()
188 188 @HasRepoPermissionAnyDecorator(
189 189 'repository.read', 'repository.write', 'repository.admin')
190 190 @view_config(
191 191 route_name='repo_summary', request_method='GET',
192 192 renderer='rhodecode:templates/summary/summary.mako')
193 193 @view_config(
194 194 route_name='repo_summary_slash', request_method='GET',
195 195 renderer='rhodecode:templates/summary/summary.mako')
196 196 @view_config(
197 197 route_name='repo_summary_explicit', request_method='GET',
198 198 renderer='rhodecode:templates/summary/summary.mako')
199 199 def summary(self):
200 200 c = self.load_default_context()
201 201
202 202 # Prepare the clone URL
203 203 self._prepare_and_set_clone_url(c)
204 204
205 205 # If enabled, get statistics data
206 206
207 207 c.show_stats = bool(self.db_repo.enable_statistics)
208 208
209 209 stats = Session().query(Statistics) \
210 210 .filter(Statistics.repository == self.db_repo) \
211 211 .scalar()
212 212
213 213 c.stats_percentage = 0
214 214
215 215 if stats and stats.languages:
216 216 c.no_data = False is self.db_repo.enable_statistics
217 217 lang_stats_d = json.loads(stats.languages)
218 218
219 219 # Sort first by decreasing count and second by the file extension,
220 220 # so we have a consistent output.
221 221 lang_stats_items = sorted(lang_stats_d.iteritems(),
222 222 key=lambda k: (-k[1], k[0]))[:10]
223 223 lang_stats = [(x, {"count": y,
224 224 "desc": LANGUAGES_EXTENSIONS_MAP.get(x)})
225 225 for x, y in lang_stats_items]
226 226
227 227 c.trending_languages = json.dumps(lang_stats)
228 228 else:
229 229 c.no_data = True
230 230 c.trending_languages = json.dumps({})
231 231
232 232 scm_model = ScmModel()
233 233 c.enable_downloads = self.db_repo.enable_downloads
234 234 c.repository_followers = scm_model.get_followers(self.db_repo)
235 235 c.repository_forks = scm_model.get_forks(self.db_repo)
236 236 c.repository_is_user_following = scm_model.is_following_repo(
237 237 self.db_repo_name, self._rhodecode_user.user_id)
238 238
239 239 # first interaction with the VCS instance after here...
240 240 if c.repository_requirements_missing:
241 241 self.request.override_renderer = \
242 242 'rhodecode:templates/summary/missing_requirements.mako'
243 243 return self._get_template_context(c)
244 244
245 245 c.readme_data, c.readme_file = \
246 246 self._get_readme_data(self.db_repo, c.visual.default_renderer)
247 247
248 248 # loads the summary commits template context
249 249 self._load_commits_context(c)
250 250
251 251 return self._get_template_context(c)
252 252
253 253 def get_request_commit_id(self):
254 254 return self.request.matchdict['commit_id']
255 255
256 256 @LoginRequired()
257 257 @HasRepoPermissionAnyDecorator(
258 258 'repository.read', 'repository.write', 'repository.admin')
259 259 @view_config(
260 260 route_name='repo_stats', request_method='GET',
261 261 renderer='json_ext')
262 262 def repo_stats(self):
263 263 commit_id = self.get_request_commit_id()
264 264 show_stats = bool(self.db_repo.enable_statistics)
265 265 repo_id = self.db_repo.repo_id
266 266
267 267 cache_seconds = safe_int(
268 268 rhodecode.CONFIG.get('rc_cache.cache_repo.expiration_time'))
269 269 cache_on = cache_seconds > 0
270 270 log.debug(
271 271 'Computing REPO TREE for repo_id %s commit_id `%s` '
272 272 'with caching: %s[TTL: %ss]' % (
273 273 repo_id, commit_id, cache_on, cache_seconds or 0))
274 274
275 275 cache_namespace_uid = 'cache_repo.{}'.format(repo_id)
276 276 region = rc_cache.get_or_create_region('cache_repo', cache_namespace_uid)
277 277
278 278 @region.conditional_cache_on_arguments(namespace=cache_namespace_uid,
279 279 condition=cache_on)
280 280 def compute_stats(repo_id, commit_id, show_stats):
281 281 code_stats = {}
282 282 size = 0
283 283 try:
284 284 scm_instance = self.db_repo.scm_instance()
285 285 commit = scm_instance.get_commit(commit_id)
286 286
287 287 for node in commit.get_filenodes_generator():
288 288 size += node.size
289 289 if not show_stats:
290 290 continue
291 291 ext = string.lower(node.extension)
292 292 ext_info = LANGUAGES_EXTENSIONS_MAP.get(ext)
293 293 if ext_info:
294 294 if ext in code_stats:
295 295 code_stats[ext]['count'] += 1
296 296 else:
297 297 code_stats[ext] = {"count": 1, "desc": ext_info}
298 298 except (EmptyRepositoryError, CommitDoesNotExistError):
299 299 pass
300 300 return {'size': h.format_byte_size_binary(size),
301 301 'code_stats': code_stats}
302 302
303 303 stats = compute_stats(self.db_repo.repo_id, commit_id, show_stats)
304 304 return stats
305 305
306 306 @LoginRequired()
307 307 @HasRepoPermissionAnyDecorator(
308 308 'repository.read', 'repository.write', 'repository.admin')
309 309 @view_config(
310 310 route_name='repo_refs_data', request_method='GET',
311 311 renderer='json_ext')
312 312 def repo_refs_data(self):
313 313 _ = self.request.translate
314 314 self.load_default_context()
315 315
316 316 repo = self.rhodecode_vcs_repo
317 317 refs_to_create = [
318 318 (_("Branch"), repo.branches, 'branch'),
319 319 (_("Tag"), repo.tags, 'tag'),
320 320 (_("Bookmark"), repo.bookmarks, 'book'),
321 321 ]
322 res = self._create_reference_data(
323 repo, self.db_repo_name, refs_to_create)
322 res = self._create_reference_data(repo, self.db_repo_name, refs_to_create)
324 323 data = {
325 324 'more': False,
326 325 'results': res
327 326 }
328 327 return data
329 328
330 329 @LoginRequired()
331 330 @HasRepoPermissionAnyDecorator(
332 331 'repository.read', 'repository.write', 'repository.admin')
333 332 @view_config(
334 333 route_name='repo_refs_changelog_data', request_method='GET',
335 334 renderer='json_ext')
336 335 def repo_refs_changelog_data(self):
337 336 _ = self.request.translate
338 337 self.load_default_context()
339 338
340 339 repo = self.rhodecode_vcs_repo
341 340
342 341 refs_to_create = [
343 342 (_("Branches"), repo.branches, 'branch'),
344 343 (_("Closed branches"), repo.branches_closed, 'branch_closed'),
345 344 # TODO: enable when vcs can handle bookmarks filters
346 345 # (_("Bookmarks"), repo.bookmarks, "book"),
347 346 ]
348 347 res = self._create_reference_data(
349 348 repo, self.db_repo_name, refs_to_create)
350 349 data = {
351 350 'more': False,
352 351 'results': res
353 352 }
354 353 return data
355 354
356 355 def _create_reference_data(self, repo, full_repo_name, refs_to_create):
357 356 format_ref_id = get_format_ref_id(repo)
358 357
359 358 result = []
360 359 for title, refs, ref_type in refs_to_create:
361 360 if refs:
362 361 result.append({
363 362 'text': title,
364 363 'children': self._create_reference_items(
365 364 repo, full_repo_name, refs, ref_type,
366 365 format_ref_id),
367 366 })
368 367 return result
369 368
370 369 def _create_reference_items(self, repo, full_repo_name, refs, ref_type, format_ref_id):
371 370 result = []
372 371 is_svn = h.is_svn(repo)
373 372 for ref_name, raw_id in refs.iteritems():
374 373 files_url = self._create_files_url(
375 374 repo, full_repo_name, ref_name, raw_id, is_svn)
376 375 result.append({
377 376 'text': ref_name,
378 377 'id': format_ref_id(ref_name, raw_id),
379 378 'raw_id': raw_id,
380 379 'type': ref_type,
381 380 'files_url': files_url,
382 381 'idx': 0,
383 382 })
384 383 return result
385 384
386 385 def _create_files_url(self, repo, full_repo_name, ref_name, raw_id, is_svn):
387 386 use_commit_id = '/' in ref_name or is_svn
388 387 return h.route_path(
389 388 'repo_files',
390 389 repo_name=full_repo_name,
391 390 f_path=ref_name if is_svn else '',
392 391 commit_id=raw_id if use_commit_id else ref_name,
393 392 _query=dict(at=ref_name))
@@ -1,350 +1,392 b''
1 1 <%inherit file="/base/base.mako"/>
2 2
3 3 <%def name="title(*args)">
4 4 ${_('{} Files').format(c.repo_name)}
5 5 %if hasattr(c,'file'):
6 6 &middot; ${(h.safe_unicode(c.file.path) or '\\')}
7 7 %endif
8 8
9 9 %if c.rhodecode_name:
10 10 &middot; ${h.branding(c.rhodecode_name)}
11 11 %endif
12 12 </%def>
13 13
14 14 <%def name="breadcrumbs_links()">
15 15 ${_('Files')}
16 16 %if c.file:
17 17 @ ${h.show_id(c.commit)}
18 18 %endif
19 19 </%def>
20 20
21 21 <%def name="menu_bar_nav()">
22 22 ${self.menu_items(active='repositories')}
23 23 </%def>
24 24
25 25 <%def name="menu_bar_subnav()">
26 26 ${self.repo_menu(active='files')}
27 27 </%def>
28 28
29 29 <%def name="main()">
30 30 <div>
31 31 <div id="files_data">
32 32 <%include file='files_pjax.mako'/>
33 33 </div>
34 34 </div>
35 35 <script>
36 36
37 37 var metadataRequest = null;
38 38 var fileSourcePage = ${c.file_source_page};
39 39 var atRef = '${request.GET.get('at', '')}';
40 40
41 41 var getState = function(context) {
42 42 var url = $(location).attr('href');
43 43 var _base_url = '${h.route_path("repo_files",repo_name=c.repo_name,commit_id='',f_path='')}';
44 44 var _annotate_url = '${h.route_path("repo_files:annotated",repo_name=c.repo_name,commit_id='',f_path='')}';
45 45 _base_url = _base_url.replace('//', '/');
46 46 _annotate_url = _annotate_url.replace('//', '/');
47 47
48 48 //extract f_path from url.
49 49 var parts = url.split(_base_url);
50 50 if (parts.length != 2) {
51 51 parts = url.split(_annotate_url);
52 52 if (parts.length != 2) {
53 53 var rev = "tip";
54 54 var f_path = "";
55 55 } else {
56 56 var parts2 = parts[1].split('/');
57 57 var rev = parts2.shift(); // pop the first element which is the revision
58 58 var f_path = parts2.join('/');
59 59 }
60 60
61 61 } else {
62 62 var parts2 = parts[1].split('/');
63 63 var rev = parts2.shift(); // pop the first element which is the revision
64 64 var f_path = parts2.join('/');
65 65 }
66 66
67 67 var url_params = {
68 68 repo_name: templateContext.repo_name,
69 69 commit_id: rev,
70 70 f_path:'__FPATH__'
71 71 };
72 72 if (atRef !== '') {
73 73 url_params['at'] = atRef
74 74 }
75 75
76 76 var _url_base = pyroutes.url('repo_files', url_params);
77 77 var _node_list_url = pyroutes.url('repo_files_nodelist',
78 78 {repo_name: templateContext.repo_name,
79 79 commit_id: rev, f_path: f_path});
80 80
81 81 return {
82 82 url: url,
83 83 f_path: f_path,
84 84 rev: rev,
85 85 commit_id: "${c.commit.raw_id}",
86 86 node_list_url: _node_list_url,
87 87 url_base: _url_base
88 88 };
89 89 };
90 90
91 91 var getFilesMetadata = function() {
92 92 if (metadataRequest && metadataRequest.readyState != 4) {
93 93 metadataRequest.abort();
94 94 }
95 95 if (fileSourcePage) {
96 96 return false;
97 97 }
98 98
99 99 if ($('#file-tree-wrapper').hasClass('full-load')) {
100 100 // in case our HTML wrapper has full-load class we don't
101 101 // trigger the async load of metadata
102 102 return false;
103 103 }
104 104
105 105 var state = getState('metadata');
106 106 var url_data = {
107 107 'repo_name': templateContext.repo_name,
108 108 'commit_id': state.commit_id,
109 109 'f_path': state.f_path
110 110 };
111 111
112 112 var url = pyroutes.url('repo_nodetree_full', url_data);
113 113
114 114 metadataRequest = $.ajax({url: url});
115 115
116 116 metadataRequest.done(function(data) {
117 117 $('#file-tree').html(data);
118 118 timeagoActivate();
119 119 });
120 120 metadataRequest.fail(function (data, textStatus, errorThrown) {
121 121 console.log(data);
122 122 if (data.status != 0) {
123 123 alert("Error while fetching metadata.\nError code {0} ({1}).Please consider reloading the page".format(data.status,data.statusText));
124 124 }
125 125 });
126 126 };
127 127
128 128 var callbacks = function() {
129 129 timeagoActivate();
130 130
131 131 if ($('#trimmed_message_box').height() < 50) {
132 132 $('#message_expand').hide();
133 133 }
134 134
135 135 $('#message_expand').on('click', function(e) {
136 136 $('#trimmed_message_box').css('max-height', 'none');
137 137 $(this).hide();
138 138 });
139 139
140 140 var state = getState('callbacks');
141 141
142 142 // VIEW FOR FILE SOURCE
143 143 if (fileSourcePage) {
144 144 // variants for with source code, not tree view
145 145
146 146 // select code link event
147 147 $("#hlcode").mouseup(getSelectionLink);
148 148
149 149 // file history select2 used for history, and switch to
150 150 var initialCommitData = {
151 151 id: null,
152 152 text: '${_("Pick Commit")}',
153 153 type: 'sha',
154 154 raw_id: null,
155 155 files_url: null
156 156 };
157 157
158 158 select2FileHistorySwitcher('#diff1', initialCommitData, state);
159 159
160 160 // show at, diff to actions handlers
161 161 $('#diff1').on('change', function(e) {
162 162 $('#diff_to_commit').removeClass('disabled').removeAttr("disabled");
163 163 $('#diff_to_commit').val(_gettext('Diff to Commit ') + e.val.truncateAfter(8, '...'));
164 164
165 165 $('#show_at_commit').removeClass('disabled').removeAttr("disabled");
166 166 $('#show_at_commit').val(_gettext('Show at Commit ') + e.val.truncateAfter(8, '...'));
167 167 });
168 168
169 169 $('#diff_to_commit').on('click', function(e) {
170 170 var diff1 = $('#diff1').val();
171 171 var diff2 = $('#diff2').val();
172 172
173 173 var url_data = {
174 174 repo_name: templateContext.repo_name,
175 175 source_ref: diff1,
176 176 source_ref_type: 'rev',
177 177 target_ref: diff2,
178 178 target_ref_type: 'rev',
179 179 merge: 1,
180 180 f_path: state.f_path
181 181 };
182 182 window.location = pyroutes.url('repo_compare', url_data);
183 183 });
184 184
185 185 $('#show_at_commit').on('click', function(e) {
186 186 var diff1 = $('#diff1').val();
187 187
188 188 var annotate = $('#annotate').val();
189 189 if (annotate === "True") {
190 190 var url = pyroutes.url('repo_files:annotated',
191 191 {'repo_name': templateContext.repo_name,
192 192 'commit_id': diff1, 'f_path': state.f_path});
193 193 } else {
194 194 var url = pyroutes.url('repo_files',
195 195 {'repo_name': templateContext.repo_name,
196 196 'commit_id': diff1, 'f_path': state.f_path});
197 197 }
198 198 window.location = url;
199 199
200 200 });
201 201
202 202 // show more authors
203 203 $('#show_authors').on('click', function(e) {
204 204 e.preventDefault();
205 205 var url = pyroutes.url('repo_file_authors',
206 206 {'repo_name': templateContext.repo_name,
207 207 'commit_id': state.rev, 'f_path': state.f_path});
208 208
209 209 $.pjax({
210 210 url: url,
211 211 data: 'annotate=${("1" if c.annotate else "0")}',
212 212 container: '#file_authors',
213 213 push: false,
214 214 timeout: 5000
215 215 }).complete(function(){
216 216 $('#show_authors').hide();
217 217 $('#file_authors_title').html(_gettext('All Authors'))
218 218 })
219 219 });
220 220
221 221 // load file short history
222 222 $('#file_history_overview').on('click', function(e) {
223 223 e.preventDefault();
224 224 path = state.f_path;
225 225 if (path.indexOf("#") >= 0) {
226 226 path = path.slice(0, path.indexOf("#"));
227 227 }
228 228 var url = pyroutes.url('repo_changelog_file',
229 229 {'repo_name': templateContext.repo_name,
230 230 'commit_id': state.rev, 'f_path': path, 'limit': 6});
231 231 $('#file_history_container').show();
232 232 $('#file_history_container').html('<div class="file-history-inner">{0}</div>'.format(_gettext('Loading ...')));
233 233
234 234 $.pjax({
235 235 url: url,
236 236 container: '#file_history_container',
237 237 push: false,
238 238 timeout: 5000
239 239 })
240 240 });
241 241
242 242 }
243 243 // VIEW FOR FILE TREE BROWSER
244 244 else {
245 245 getFilesMetadata();
246 246
247 247 // fuzzy file filter
248 248 fileBrowserListeners(state.node_list_url, state.url_base);
249 249
250 250 // switch to widget
251 251 var initialCommitData = {
252 252 at_ref: atRef,
253 253 id: null,
254 254 text: '${c.commit.raw_id}',
255 255 type: 'sha',
256 256 raw_id: '${c.commit.raw_id}',
257 257 idx: ${c.commit.idx},
258 258 files_url: null,
259 259 };
260 260
261 261 // check if we have ref info.
262 262 var selectedRef = fileTreeRefs[atRef];
263 263 if (selectedRef !== undefined) {
264 264 $.extend(initialCommitData, selectedRef)
265 265 }
266 266
267 267 var loadUrl = pyroutes.url('repo_refs_data', {'repo_name': templateContext.repo_name});
268 var cacheKey = '__ALL_FILE_REFS__';
269 var cachedDataSource = {};
270
271 var loadRefsData = function (query) {
272 $.ajax({
273 url: loadUrl,
274 data: {},
275 dataType: 'json',
276 type: 'GET',
277 success: function (data) {
278 cachedDataSource[cacheKey] = data;
279 query.callback({results: data.results});
280 }
281 });
282 };
283
284 var feedRefsData = function (query, cachedData) {
285 var data = {results: []};
286 //filter results
287 $.each(cachedData.results, function () {
288 var section = this.text;
289 var children = [];
290 $.each(this.children, function () {
291 if (query.term.length === 0 || this.text.toUpperCase().indexOf(query.term.toUpperCase()) >= 0) {
292 children.push(this)
293 }
294 });
295 data.results.push({
296 'text': section,
297 'children': children
298 })
299 });
300
301 //push the typed in commit idx
302 if (!isNaN(query.term)) {
303 var files_url = pyroutes.url('repo_files',
304 {'repo_name': templateContext.repo_name,
305 'commit_id': query.term, 'f_path': state.f_path});
306
307 data.results.push({
308 'text': _gettext('go to numeric commit'),
309 'children': [{
310 at_ref: null,
311 id: null,
312 text: 'r{0}'.format(query.term),
313 type: 'sha',
314 raw_id: query.term,
315 idx: query.term,
316 files_url: files_url,
317 }]
318 });
319 }
320 query.callback(data);
321 };
268 322
269 323 var select2RefFileSwitcher = function (targetElement, loadUrl, initialData) {
270 324 var formatResult = function (result, container, query) {
271 325 return formatSelect2SelectionRefs(result);
272 326 };
273 327
274 328 var formatSelection = function (data, container) {
275 329 var commit_ref = data;
276 330
277 331 var tmpl = '';
278 332 if (commit_ref.type === 'sha') {
279 333 tmpl = commit_ref.raw_id.substr(0,8);
280 334 } else if (commit_ref.type === 'branch') {
281 335 tmpl = tmpl.concat('<i class="icon-branch"></i> ');
282 336 tmpl = tmpl.concat(escapeHtml(commit_ref.text));
283 337 } else if (commit_ref.type === 'tag') {
284 338 tmpl = tmpl.concat('<i class="icon-tag"></i> ');
285 339 tmpl = tmpl.concat(escapeHtml(commit_ref.text));
286 340 } else if (commit_ref.type === 'book') {
287 341 tmpl = tmpl.concat('<i class="icon-bookmark"></i> ');
288 342 tmpl = tmpl.concat(escapeHtml(commit_ref.text));
289 343 }
290 344
291 tmpl = tmpl.concat('<span class="select-index-number">{0}</span>'.format(commit_ref.idx));
345 tmpl = tmpl.concat('<span class="select-index-number">r{0}</span>'.format(commit_ref.idx));
292 346 return tmpl
293 347 };
294 348
295 349 $(targetElement).select2({
296 cachedDataSource: {},
297 350 dropdownAutoWidth: true,
298 351 width: "resolve",
299 352 containerCssClass: "drop-menu",
300 353 dropdownCssClass: "drop-menu-dropdown",
301 354 query: function(query) {
302 var self = this;
303 var cacheKey = '__ALL_FILE_REFS__';
304 var cachedData = self.cachedDataSource[cacheKey];
355
356 var cachedData = cachedDataSource[cacheKey];
305 357 if (cachedData) {
306 var data = select2RefFilterResults(query.term, cachedData);
307 query.callback({results: data.results});
358 feedRefsData(query, cachedData)
308 359 } else {
309 $.ajax({
310 url: loadUrl,
311 data: {},
312 dataType: 'json',
313 type: 'GET',
314 success: function(data) {
315 self.cachedDataSource[cacheKey] = data;
316 query.callback({results: data.results});
317 }
318 });
360 loadRefsData(query)
319 361 }
320 362 },
321 363 initSelection: function(element, callback) {
322 364 callback(initialData);
323 365 },
324 366 formatResult: formatResult,
325 367 formatSelection: formatSelection
326 368 });
327 369
328 370 };
329 371
330 372 select2RefFileSwitcher('#refs_filter', loadUrl, initialCommitData);
331 373
332 374 $('#refs_filter').on('change', function(e) {
333 375 var data = $('#refs_filter').select2('data');
334 376 window.location = data.files_url
335 377 });
336 378
337 379 }
338 380 };
339 381
340 382 $(document).ready(function() {
341 383 callbacks();
342 384 var search_GET = "${request.GET.get('search','')}";
343 385 if (search_GET === "1") {
344 386 _NODEFILTER.initFilter();
345 387 }
346 388 });
347 389
348 390 </script>
349 391
350 392 </%def> No newline at end of file
General Comments 0
You need to be logged in to leave comments. Login now