##// END OF EJS Templates
js: tooltip allow full html mode using a base64 encoded data property.
marcink -
r4031:8ddabfbf default
parent child Browse files
Show More
@@ -1,656 +1,661 b''
1 // # Copyright (C) 2010-2019 RhodeCode GmbH
1 // # Copyright (C) 2010-2019 RhodeCode GmbH
2 // #
2 // #
3 // # This program is free software: you can redistribute it and/or modify
3 // # This program is free software: you can redistribute it and/or modify
4 // # it under the terms of the GNU Affero General Public License, version 3
4 // # it under the terms of the GNU Affero General Public License, version 3
5 // # (only), as published by the Free Software Foundation.
5 // # (only), as published by the Free Software Foundation.
6 // #
6 // #
7 // # This program is distributed in the hope that it will be useful,
7 // # This program is distributed in the hope that it will be useful,
8 // # but WITHOUT ANY WARRANTY; without even the implied warranty of
8 // # but WITHOUT ANY WARRANTY; without even the implied warranty of
9 // # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9 // # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 // # GNU General Public License for more details.
10 // # GNU General Public License for more details.
11 // #
11 // #
12 // # You should have received a copy of the GNU Affero General Public License
12 // # You should have received a copy of the GNU Affero General Public License
13 // # along with this program. If not, see <http://www.gnu.org/licenses/>.
13 // # along with this program. If not, see <http://www.gnu.org/licenses/>.
14 // #
14 // #
15 // # This program is dual-licensed. If you wish to learn more about the
15 // # This program is dual-licensed. If you wish to learn more about the
16 // # RhodeCode Enterprise Edition, including its added features, Support services,
16 // # RhodeCode Enterprise Edition, including its added features, Support services,
17 // # and proprietary license terms, please see https://rhodecode.com/licenses/
17 // # and proprietary license terms, please see https://rhodecode.com/licenses/
18
18
19 /**
19 /**
20 RhodeCode JS Files
20 RhodeCode JS Files
21 **/
21 **/
22
22
23 if (typeof console == "undefined" || typeof console.log == "undefined"){
23 if (typeof console == "undefined" || typeof console.log == "undefined"){
24 console = { log: function() {} }
24 console = { log: function() {} }
25 }
25 }
26
26
27 // TODO: move the following function to submodules
27 // TODO: move the following function to submodules
28
28
29 /**
29 /**
30 * show more
30 * show more
31 */
31 */
32 var show_more_event = function(){
32 var show_more_event = function(){
33 $('table .show_more').click(function(e) {
33 $('table .show_more').click(function(e) {
34 var cid = e.target.id.substring(1);
34 var cid = e.target.id.substring(1);
35 var button = $(this);
35 var button = $(this);
36 if (button.hasClass('open')) {
36 if (button.hasClass('open')) {
37 $('#'+cid).hide();
37 $('#'+cid).hide();
38 button.removeClass('open');
38 button.removeClass('open');
39 } else {
39 } else {
40 $('#'+cid).show();
40 $('#'+cid).show();
41 button.addClass('open one');
41 button.addClass('open one');
42 }
42 }
43 });
43 });
44 };
44 };
45
45
46 var compare_radio_buttons = function(repo_name, compare_ref_type){
46 var compare_radio_buttons = function(repo_name, compare_ref_type){
47 $('#compare_action').on('click', function(e){
47 $('#compare_action').on('click', function(e){
48 e.preventDefault();
48 e.preventDefault();
49
49
50 var source = $('input[name=compare_source]:checked').val();
50 var source = $('input[name=compare_source]:checked').val();
51 var target = $('input[name=compare_target]:checked').val();
51 var target = $('input[name=compare_target]:checked').val();
52 if(source && target){
52 if(source && target){
53 var url_data = {
53 var url_data = {
54 repo_name: repo_name,
54 repo_name: repo_name,
55 source_ref: source,
55 source_ref: source,
56 source_ref_type: compare_ref_type,
56 source_ref_type: compare_ref_type,
57 target_ref: target,
57 target_ref: target,
58 target_ref_type: compare_ref_type,
58 target_ref_type: compare_ref_type,
59 merge: 1
59 merge: 1
60 };
60 };
61 window.location = pyroutes.url('repo_compare', url_data);
61 window.location = pyroutes.url('repo_compare', url_data);
62 }
62 }
63 });
63 });
64 $('.compare-radio-button').on('click', function(e){
64 $('.compare-radio-button').on('click', function(e){
65 var source = $('input[name=compare_source]:checked').val();
65 var source = $('input[name=compare_source]:checked').val();
66 var target = $('input[name=compare_target]:checked').val();
66 var target = $('input[name=compare_target]:checked').val();
67 if(source && target){
67 if(source && target){
68 $('#compare_action').removeAttr("disabled");
68 $('#compare_action').removeAttr("disabled");
69 $('#compare_action').removeClass("disabled");
69 $('#compare_action').removeClass("disabled");
70 }
70 }
71 })
71 })
72 };
72 };
73
73
74 var showRepoSize = function(target, repo_name, commit_id, callback) {
74 var showRepoSize = function(target, repo_name, commit_id, callback) {
75 var container = $('#' + target);
75 var container = $('#' + target);
76 var url = pyroutes.url('repo_stats',
76 var url = pyroutes.url('repo_stats',
77 {"repo_name": repo_name, "commit_id": commit_id});
77 {"repo_name": repo_name, "commit_id": commit_id});
78
78
79 container.show();
79 container.show();
80 if (!container.hasClass('loaded')) {
80 if (!container.hasClass('loaded')) {
81 $.ajax({url: url})
81 $.ajax({url: url})
82 .complete(function (data) {
82 .complete(function (data) {
83 var responseJSON = data.responseJSON;
83 var responseJSON = data.responseJSON;
84 container.addClass('loaded');
84 container.addClass('loaded');
85 container.html(responseJSON.size);
85 container.html(responseJSON.size);
86 callback(responseJSON.code_stats)
86 callback(responseJSON.code_stats)
87 })
87 })
88 .fail(function (data) {
88 .fail(function (data) {
89 console.log('failed to load repo stats');
89 console.log('failed to load repo stats');
90 });
90 });
91 }
91 }
92
92
93 };
93 };
94
94
95 var showRepoStats = function(target, data){
95 var showRepoStats = function(target, data){
96 var container = $('#' + target);
96 var container = $('#' + target);
97
97
98 if (container.hasClass('loaded')) {
98 if (container.hasClass('loaded')) {
99 return
99 return
100 }
100 }
101
101
102 var total = 0;
102 var total = 0;
103 var no_data = true;
103 var no_data = true;
104 var tbl = document.createElement('table');
104 var tbl = document.createElement('table');
105 tbl.setAttribute('class', 'trending_language_tbl rctable');
105 tbl.setAttribute('class', 'trending_language_tbl rctable');
106
106
107 $.each(data, function(key, val){
107 $.each(data, function(key, val){
108 total += val.count;
108 total += val.count;
109 });
109 });
110
110
111 var sortedStats = [];
111 var sortedStats = [];
112 for (var obj in data){
112 for (var obj in data){
113 sortedStats.push([obj, data[obj]])
113 sortedStats.push([obj, data[obj]])
114 }
114 }
115 var sortedData = sortedStats.sort(function (a, b) {
115 var sortedData = sortedStats.sort(function (a, b) {
116 return b[1].count - a[1].count
116 return b[1].count - a[1].count
117 });
117 });
118 var cnt = 0;
118 var cnt = 0;
119 $.each(sortedData, function(idx, val){
119 $.each(sortedData, function(idx, val){
120 cnt += 1;
120 cnt += 1;
121 no_data = false;
121 no_data = false;
122
122
123 var tr = document.createElement('tr');
123 var tr = document.createElement('tr');
124
124
125 var key = val[0];
125 var key = val[0];
126 var obj = {"desc": val[1].desc, "count": val[1].count};
126 var obj = {"desc": val[1].desc, "count": val[1].count};
127
127
128 // meta language names
128 // meta language names
129 var td1 = document.createElement('td');
129 var td1 = document.createElement('td');
130 var trending_language_label = document.createElement('div');
130 var trending_language_label = document.createElement('div');
131 trending_language_label.innerHTML = obj.desc;
131 trending_language_label.innerHTML = obj.desc;
132 td1.appendChild(trending_language_label);
132 td1.appendChild(trending_language_label);
133
133
134 // extensions
134 // extensions
135 var td2 = document.createElement('td');
135 var td2 = document.createElement('td');
136 var extension = document.createElement('div');
136 var extension = document.createElement('div');
137 extension.innerHTML = ".{0}".format(key)
137 extension.innerHTML = ".{0}".format(key)
138 td2.appendChild(extension);
138 td2.appendChild(extension);
139
139
140 // number of files
140 // number of files
141 var td3 = document.createElement('td');
141 var td3 = document.createElement('td');
142 var file_count = document.createElement('div');
142 var file_count = document.createElement('div');
143 var percentage_num = Math.round((obj.count / total * 100), 2);
143 var percentage_num = Math.round((obj.count / total * 100), 2);
144 var label = _ngettext('file', 'files', obj.count);
144 var label = _ngettext('file', 'files', obj.count);
145 file_count.innerHTML = "{0} {1} ({2}%)".format(obj.count, label, percentage_num) ;
145 file_count.innerHTML = "{0} {1} ({2}%)".format(obj.count, label, percentage_num) ;
146 td3.appendChild(file_count);
146 td3.appendChild(file_count);
147
147
148 // percentage
148 // percentage
149 var td4 = document.createElement('td');
149 var td4 = document.createElement('td');
150 td4.setAttribute("class", 'trending_language');
150 td4.setAttribute("class", 'trending_language');
151
151
152 var percentage = document.createElement('div');
152 var percentage = document.createElement('div');
153 percentage.setAttribute('class', 'lang-bar');
153 percentage.setAttribute('class', 'lang-bar');
154 percentage.innerHTML = "&nbsp;";
154 percentage.innerHTML = "&nbsp;";
155 percentage.style.width = percentage_num + '%';
155 percentage.style.width = percentage_num + '%';
156 td4.appendChild(percentage);
156 td4.appendChild(percentage);
157
157
158 tr.appendChild(td1);
158 tr.appendChild(td1);
159 tr.appendChild(td2);
159 tr.appendChild(td2);
160 tr.appendChild(td3);
160 tr.appendChild(td3);
161 tr.appendChild(td4);
161 tr.appendChild(td4);
162 tbl.appendChild(tr);
162 tbl.appendChild(tr);
163
163
164 });
164 });
165
165
166 $(container).html(tbl);
166 $(container).html(tbl);
167 $(container).addClass('loaded');
167 $(container).addClass('loaded');
168
168
169 $('#code_stats_show_more').on('click', function (e) {
169 $('#code_stats_show_more').on('click', function (e) {
170 e.preventDefault();
170 e.preventDefault();
171 $('.stats_hidden').each(function (idx) {
171 $('.stats_hidden').each(function (idx) {
172 $(this).css("display", "");
172 $(this).css("display", "");
173 });
173 });
174 $('#code_stats_show_more').hide();
174 $('#code_stats_show_more').hide();
175 });
175 });
176
176
177 };
177 };
178
178
179 // returns a node from given html;
179 // returns a node from given html;
180 var fromHTML = function(html){
180 var fromHTML = function(html){
181 var _html = document.createElement('element');
181 var _html = document.createElement('element');
182 _html.innerHTML = html;
182 _html.innerHTML = html;
183 return _html;
183 return _html;
184 };
184 };
185
185
186 // Toggle Collapsable Content
186 // Toggle Collapsable Content
187 function collapsableContent() {
187 function collapsableContent() {
188
188
189 $('.collapsable-content').not('.no-hide').hide();
189 $('.collapsable-content').not('.no-hide').hide();
190
190
191 $('.btn-collapse').unbind(); //in case we've been here before
191 $('.btn-collapse').unbind(); //in case we've been here before
192 $('.btn-collapse').click(function() {
192 $('.btn-collapse').click(function() {
193 var button = $(this);
193 var button = $(this);
194 var togglename = $(this).data("toggle");
194 var togglename = $(this).data("toggle");
195 $('.collapsable-content[data-toggle='+togglename+']').toggle();
195 $('.collapsable-content[data-toggle='+togglename+']').toggle();
196 if ($(this).html()=="Show Less")
196 if ($(this).html()=="Show Less")
197 $(this).html("Show More");
197 $(this).html("Show More");
198 else
198 else
199 $(this).html("Show Less");
199 $(this).html("Show Less");
200 });
200 });
201 };
201 };
202
202
203 var timeagoActivate = function() {
203 var timeagoActivate = function() {
204 $("time.timeago").timeago();
204 $("time.timeago").timeago();
205 };
205 };
206
206
207
207
208 var clipboardActivate = function() {
208 var clipboardActivate = function() {
209 /*
209 /*
210 *
210 *
211 * <i class="tooltip icon-plus clipboard-action" data-clipboard-text="${commit.raw_id}" title="${_('Copy the full commit id')}"></i>
211 * <i class="tooltip icon-plus clipboard-action" data-clipboard-text="${commit.raw_id}" title="${_('Copy the full commit id')}"></i>
212 * */
212 * */
213 var clipboard = new ClipboardJS('.clipboard-action');
213 var clipboard = new ClipboardJS('.clipboard-action');
214
214
215 clipboard.on('success', function(e) {
215 clipboard.on('success', function(e) {
216 var callback = function () {
216 var callback = function () {
217 $(e.trigger).animate({'opacity': 1.00}, 200)
217 $(e.trigger).animate({'opacity': 1.00}, 200)
218 };
218 };
219 $(e.trigger).animate({'opacity': 0.15}, 200, callback);
219 $(e.trigger).animate({'opacity': 0.15}, 200, callback);
220 e.clearSelection();
220 e.clearSelection();
221 });
221 });
222 };
222 };
223
223
224 var tooltipActivate = function () {
224 var tooltipActivate = function () {
225 var delay = 50;
225 var delay = 50;
226 var animation = 'fade';
226 var animation = 'fade';
227 var theme = 'tooltipster-shadow';
227 var theme = 'tooltipster-shadow';
228 var debug = false;
228 var debug = false;
229
229
230 $('.tooltip').tooltipster({
230 $('.tooltip').tooltipster({
231 debug: debug,
231 debug: debug,
232 theme: theme,
232 theme: theme,
233 animation: animation,
233 animation: animation,
234 delay: delay,
234 delay: delay,
235 contentCloning: true,
235 contentCloning: true,
236 contentAsHTML: true,
236 contentAsHTML: true,
237
237
238 functionBefore: function (instance, helper) {
238 functionBefore: function (instance, helper) {
239 var $origin = $(helper.origin);
239 var $origin = $(helper.origin);
240 var data = '<div style="white-space: pre-wrap">{0}</div>'.format(instance.content());
240 var data = '<div style="white-space: pre-wrap">{0}</div>'.format(instance.content());
241 instance.content(data);
241 instance.content(data);
242 }
242 }
243 });
243 });
244 var hovercardCache = {};
244 var hovercardCache = {};
245
245
246 var loadHoverCard = function (url, callback) {
246 var loadHoverCard = function (url, callback) {
247 var id = url;
247 var id = url;
248
248
249 if (hovercardCache[id] !== undefined) {
249 if (hovercardCache[id] !== undefined) {
250 callback(hovercardCache[id]);
250 callback(hovercardCache[id]);
251 return;
251 return;
252 }
252 }
253
253
254 hovercardCache[id] = undefined;
254 hovercardCache[id] = undefined;
255 $.get(url, function (data) {
255 $.get(url, function (data) {
256 hovercardCache[id] = data;
256 hovercardCache[id] = data;
257 callback(hovercardCache[id]);
257 callback(hovercardCache[id]);
258 }).fail(function (data, textStatus, errorThrown) {
258 }).fail(function (data, textStatus, errorThrown) {
259 var msg = "Error while fetching hovercard.\nError code {0} ({1}).".format(data.status,data.statusText);
259 var msg = "Error while fetching hovercard.\nError code {0} ({1}).".format(data.status,data.statusText);
260 callback(msg);
260 callback(msg);
261 });
261 });
262 };
262 };
263
263
264 $('.tooltip-hovercard').tooltipster({
264 $('.tooltip-hovercard').tooltipster({
265 debug: debug,
265 debug: debug,
266 theme: theme,
266 theme: theme,
267 animation: animation,
267 animation: animation,
268 delay: delay,
268 delay: delay,
269 interactive: true,
269 interactive: true,
270 contentCloning: true,
270 contentCloning: true,
271
271
272 trigger: 'custom',
272 trigger: 'custom',
273 triggerOpen: {
273 triggerOpen: {
274 mouseenter: true,
274 mouseenter: true,
275 },
275 },
276 triggerClose: {
276 triggerClose: {
277 mouseleave: true,
277 mouseleave: true,
278 originClick: true,
278 originClick: true,
279 touchleave: true
279 touchleave: true
280 },
280 },
281 content: _gettext('Loading...'),
281 content: _gettext('Loading...'),
282 contentAsHTML: true,
282 contentAsHTML: true,
283 updateAnimation: null,
283 updateAnimation: null,
284
284
285 functionBefore: function (instance, helper) {
285 functionBefore: function (instance, helper) {
286
286
287 var $origin = $(helper.origin);
287 var $origin = $(helper.origin);
288
288
289 // we set a variable so the data is only loaded once via Ajax, not every time the tooltip opens
289 // we set a variable so the data is only loaded once via Ajax, not every time the tooltip opens
290 if ($origin.data('loaded') !== true) {
290 if ($origin.data('loaded') !== true) {
291 var hovercardUrl = $origin.data('hovercardUrl');
291 var hovercardUrl = $origin.data('hovercardUrl');
292
292
293 if (hovercardUrl !== undefined && hovercardUrl !== "") {
293 if (hovercardUrl !== undefined && hovercardUrl !== "") {
294 loadHoverCard(hovercardUrl, function (data) {
294 loadHoverCard(hovercardUrl, function (data) {
295 instance.content(data);
295 instance.content(data);
296 })
296 })
297 } else {
297 } else {
298 var data = '<div style="white-space: pre-wrap">{0}</div>'.format($origin.data('hovercardAlt'))
298 if ($origin.data('hovercardAltHtml')) {
299 var data = atob($origin.data('hovercardAltHtml'));
300 } else {
301 var data = '<div style="white-space: pre-wrap">{0}</div>'.format($origin.data('hovercardAlt'))
302 }
303
299 instance.content(data);
304 instance.content(data);
300 }
305 }
301
306
302 // to remember that the data has been loaded
307 // to remember that the data has been loaded
303 $origin.data('loaded', true);
308 $origin.data('loaded', true);
304 }
309 }
305 }
310 }
306 })
311 })
307 };
312 };
308
313
309 // Formatting values in a Select2 dropdown of commit references
314 // Formatting values in a Select2 dropdown of commit references
310 var formatSelect2SelectionRefs = function(commit_ref){
315 var formatSelect2SelectionRefs = function(commit_ref){
311 var tmpl = '';
316 var tmpl = '';
312 if (!commit_ref.text || commit_ref.type === 'sha'){
317 if (!commit_ref.text || commit_ref.type === 'sha'){
313 return commit_ref.text;
318 return commit_ref.text;
314 }
319 }
315 if (commit_ref.type === 'branch'){
320 if (commit_ref.type === 'branch'){
316 tmpl = tmpl.concat('<i class="icon-branch"></i> ');
321 tmpl = tmpl.concat('<i class="icon-branch"></i> ');
317 } else if (commit_ref.type === 'tag'){
322 } else if (commit_ref.type === 'tag'){
318 tmpl = tmpl.concat('<i class="icon-tag"></i> ');
323 tmpl = tmpl.concat('<i class="icon-tag"></i> ');
319 } else if (commit_ref.type === 'book'){
324 } else if (commit_ref.type === 'book'){
320 tmpl = tmpl.concat('<i class="icon-bookmark"></i> ');
325 tmpl = tmpl.concat('<i class="icon-bookmark"></i> ');
321 }
326 }
322 return tmpl.concat(escapeHtml(commit_ref.text));
327 return tmpl.concat(escapeHtml(commit_ref.text));
323 };
328 };
324
329
325 // takes a given html element and scrolls it down offset pixels
330 // takes a given html element and scrolls it down offset pixels
326 function offsetScroll(element, offset) {
331 function offsetScroll(element, offset) {
327 setTimeout(function() {
332 setTimeout(function() {
328 var location = element.offset().top;
333 var location = element.offset().top;
329 // some browsers use body, some use html
334 // some browsers use body, some use html
330 $('html, body').animate({ scrollTop: (location - offset) });
335 $('html, body').animate({ scrollTop: (location - offset) });
331 }, 100);
336 }, 100);
332 }
337 }
333
338
334 // scroll an element `percent`% from the top of page in `time` ms
339 // scroll an element `percent`% from the top of page in `time` ms
335 function scrollToElement(element, percent, time) {
340 function scrollToElement(element, percent, time) {
336 percent = (percent === undefined ? 25 : percent);
341 percent = (percent === undefined ? 25 : percent);
337 time = (time === undefined ? 100 : time);
342 time = (time === undefined ? 100 : time);
338
343
339 var $element = $(element);
344 var $element = $(element);
340 if ($element.length == 0) {
345 if ($element.length == 0) {
341 throw('Cannot scroll to {0}'.format(element))
346 throw('Cannot scroll to {0}'.format(element))
342 }
347 }
343 var elOffset = $element.offset().top;
348 var elOffset = $element.offset().top;
344 var elHeight = $element.height();
349 var elHeight = $element.height();
345 var windowHeight = $(window).height();
350 var windowHeight = $(window).height();
346 var offset = elOffset;
351 var offset = elOffset;
347 if (elHeight < windowHeight) {
352 if (elHeight < windowHeight) {
348 offset = elOffset - ((windowHeight / (100 / percent)) - (elHeight / 2));
353 offset = elOffset - ((windowHeight / (100 / percent)) - (elHeight / 2));
349 }
354 }
350 setTimeout(function() {
355 setTimeout(function() {
351 $('html, body').animate({ scrollTop: offset});
356 $('html, body').animate({ scrollTop: offset});
352 }, time);
357 }, time);
353 }
358 }
354
359
355 /**
360 /**
356 * global hooks after DOM is loaded
361 * global hooks after DOM is loaded
357 */
362 */
358 $(document).ready(function() {
363 $(document).ready(function() {
359 firefoxAnchorFix();
364 firefoxAnchorFix();
360
365
361 $('.navigation a.menulink').on('click', function(e){
366 $('.navigation a.menulink').on('click', function(e){
362 var menuitem = $(this).parent('li');
367 var menuitem = $(this).parent('li');
363 if (menuitem.hasClass('open')) {
368 if (menuitem.hasClass('open')) {
364 menuitem.removeClass('open');
369 menuitem.removeClass('open');
365 } else {
370 } else {
366 menuitem.addClass('open');
371 menuitem.addClass('open');
367 $(document).on('click', function(event) {
372 $(document).on('click', function(event) {
368 if (!$(event.target).closest(menuitem).length) {
373 if (!$(event.target).closest(menuitem).length) {
369 menuitem.removeClass('open');
374 menuitem.removeClass('open');
370 }
375 }
371 });
376 });
372 }
377 }
373 });
378 });
374
379
375 $('body').on('click', '.cb-lineno a', function(event) {
380 $('body').on('click', '.cb-lineno a', function(event) {
376 function sortNumber(a,b) {
381 function sortNumber(a,b) {
377 return a - b;
382 return a - b;
378 }
383 }
379
384
380 var lineNo = $(this).data('lineNo');
385 var lineNo = $(this).data('lineNo');
381 var lineName = $(this).attr('name');
386 var lineName = $(this).attr('name');
382
387
383 if (lineNo) {
388 if (lineNo) {
384 var prevLine = $('.cb-line-selected a').data('lineNo');
389 var prevLine = $('.cb-line-selected a').data('lineNo');
385
390
386 // on shift, we do a range selection, if we got previous line
391 // on shift, we do a range selection, if we got previous line
387 if (event.shiftKey && prevLine !== undefined) {
392 if (event.shiftKey && prevLine !== undefined) {
388 var prevLine = parseInt(prevLine);
393 var prevLine = parseInt(prevLine);
389 var nextLine = parseInt(lineNo);
394 var nextLine = parseInt(lineNo);
390 var pos = [prevLine, nextLine].sort(sortNumber);
395 var pos = [prevLine, nextLine].sort(sortNumber);
391 var anchor = '#L{0}-{1}'.format(pos[0], pos[1]);
396 var anchor = '#L{0}-{1}'.format(pos[0], pos[1]);
392
397
393 // single click
398 // single click
394 } else {
399 } else {
395 var nextLine = parseInt(lineNo);
400 var nextLine = parseInt(lineNo);
396 var pos = [nextLine, nextLine];
401 var pos = [nextLine, nextLine];
397 var anchor = '#L{0}'.format(pos[0]);
402 var anchor = '#L{0}'.format(pos[0]);
398
403
399 }
404 }
400 // highlight
405 // highlight
401 var range = [];
406 var range = [];
402 for (var i = pos[0]; i <= pos[1]; i++) {
407 for (var i = pos[0]; i <= pos[1]; i++) {
403 range.push(i);
408 range.push(i);
404 }
409 }
405 // clear old selected lines
410 // clear old selected lines
406 $('.cb-line-selected').removeClass('cb-line-selected');
411 $('.cb-line-selected').removeClass('cb-line-selected');
407
412
408 $.each(range, function (i, lineNo) {
413 $.each(range, function (i, lineNo) {
409 var line_td = $('td.cb-lineno#L' + lineNo);
414 var line_td = $('td.cb-lineno#L' + lineNo);
410
415
411 if (line_td.length) {
416 if (line_td.length) {
412 line_td.addClass('cb-line-selected'); // line number td
417 line_td.addClass('cb-line-selected'); // line number td
413 line_td.prev().addClass('cb-line-selected'); // line data
418 line_td.prev().addClass('cb-line-selected'); // line data
414 line_td.next().addClass('cb-line-selected'); // line content
419 line_td.next().addClass('cb-line-selected'); // line content
415 }
420 }
416 });
421 });
417
422
418 } else if (lineName !== undefined) { // lineName only occurs in diffs
423 } else if (lineName !== undefined) { // lineName only occurs in diffs
419 // clear old selected lines
424 // clear old selected lines
420 $('td.cb-line-selected').removeClass('cb-line-selected');
425 $('td.cb-line-selected').removeClass('cb-line-selected');
421 var anchor = '#{0}'.format(lineName);
426 var anchor = '#{0}'.format(lineName);
422 var diffmode = templateContext.session_attrs.diffmode || "sideside";
427 var diffmode = templateContext.session_attrs.diffmode || "sideside";
423
428
424 if (diffmode === "unified") {
429 if (diffmode === "unified") {
425 $(this).closest('tr').find('td').addClass('cb-line-selected');
430 $(this).closest('tr').find('td').addClass('cb-line-selected');
426 } else {
431 } else {
427 var activeTd = $(this).closest('td');
432 var activeTd = $(this).closest('td');
428 activeTd.addClass('cb-line-selected');
433 activeTd.addClass('cb-line-selected');
429 activeTd.next('td').addClass('cb-line-selected');
434 activeTd.next('td').addClass('cb-line-selected');
430 }
435 }
431
436
432 }
437 }
433
438
434 // Replace URL without jumping to it if browser supports.
439 // Replace URL without jumping to it if browser supports.
435 // Default otherwise
440 // Default otherwise
436 if (history.pushState && anchor !== undefined) {
441 if (history.pushState && anchor !== undefined) {
437 var new_location = location.href.rstrip('#');
442 var new_location = location.href.rstrip('#');
438 if (location.hash) {
443 if (location.hash) {
439 // location without hash
444 // location without hash
440 new_location = new_location.replace(location.hash, "");
445 new_location = new_location.replace(location.hash, "");
441 }
446 }
442
447
443 // Make new anchor url
448 // Make new anchor url
444 new_location = new_location + anchor;
449 new_location = new_location + anchor;
445 history.pushState(true, document.title, new_location);
450 history.pushState(true, document.title, new_location);
446
451
447 return false;
452 return false;
448 }
453 }
449
454
450 });
455 });
451
456
452 $('.collapse_file').on('click', function(e) {
457 $('.collapse_file').on('click', function(e) {
453 e.stopPropagation();
458 e.stopPropagation();
454 if ($(e.target).is('a')) { return; }
459 if ($(e.target).is('a')) { return; }
455 var node = $(e.delegateTarget).first();
460 var node = $(e.delegateTarget).first();
456 var icon = $($(node.children().first()).children().first());
461 var icon = $($(node.children().first()).children().first());
457 var id = node.attr('fid');
462 var id = node.attr('fid');
458 var target = $('#'+id);
463 var target = $('#'+id);
459 var tr = $('#tr_'+id);
464 var tr = $('#tr_'+id);
460 var diff = $('#diff_'+id);
465 var diff = $('#diff_'+id);
461 if(node.hasClass('expand_file')){
466 if(node.hasClass('expand_file')){
462 node.removeClass('expand_file');
467 node.removeClass('expand_file');
463 icon.removeClass('expand_file_icon');
468 icon.removeClass('expand_file_icon');
464 node.addClass('collapse_file');
469 node.addClass('collapse_file');
465 icon.addClass('collapse_file_icon');
470 icon.addClass('collapse_file_icon');
466 diff.show();
471 diff.show();
467 tr.show();
472 tr.show();
468 target.show();
473 target.show();
469 } else {
474 } else {
470 node.removeClass('collapse_file');
475 node.removeClass('collapse_file');
471 icon.removeClass('collapse_file_icon');
476 icon.removeClass('collapse_file_icon');
472 node.addClass('expand_file');
477 node.addClass('expand_file');
473 icon.addClass('expand_file_icon');
478 icon.addClass('expand_file_icon');
474 diff.hide();
479 diff.hide();
475 tr.hide();
480 tr.hide();
476 target.hide();
481 target.hide();
477 }
482 }
478 });
483 });
479
484
480 $('#expand_all_files').click(function() {
485 $('#expand_all_files').click(function() {
481 $('.expand_file').each(function() {
486 $('.expand_file').each(function() {
482 var node = $(this);
487 var node = $(this);
483 var icon = $($(node.children().first()).children().first());
488 var icon = $($(node.children().first()).children().first());
484 var id = $(this).attr('fid');
489 var id = $(this).attr('fid');
485 var target = $('#'+id);
490 var target = $('#'+id);
486 var tr = $('#tr_'+id);
491 var tr = $('#tr_'+id);
487 var diff = $('#diff_'+id);
492 var diff = $('#diff_'+id);
488 node.removeClass('expand_file');
493 node.removeClass('expand_file');
489 icon.removeClass('expand_file_icon');
494 icon.removeClass('expand_file_icon');
490 node.addClass('collapse_file');
495 node.addClass('collapse_file');
491 icon.addClass('collapse_file_icon');
496 icon.addClass('collapse_file_icon');
492 diff.show();
497 diff.show();
493 tr.show();
498 tr.show();
494 target.show();
499 target.show();
495 });
500 });
496 });
501 });
497
502
498 $('#collapse_all_files').click(function() {
503 $('#collapse_all_files').click(function() {
499 $('.collapse_file').each(function() {
504 $('.collapse_file').each(function() {
500 var node = $(this);
505 var node = $(this);
501 var icon = $($(node.children().first()).children().first());
506 var icon = $($(node.children().first()).children().first());
502 var id = $(this).attr('fid');
507 var id = $(this).attr('fid');
503 var target = $('#'+id);
508 var target = $('#'+id);
504 var tr = $('#tr_'+id);
509 var tr = $('#tr_'+id);
505 var diff = $('#diff_'+id);
510 var diff = $('#diff_'+id);
506 node.removeClass('collapse_file');
511 node.removeClass('collapse_file');
507 icon.removeClass('collapse_file_icon');
512 icon.removeClass('collapse_file_icon');
508 node.addClass('expand_file');
513 node.addClass('expand_file');
509 icon.addClass('expand_file_icon');
514 icon.addClass('expand_file_icon');
510 diff.hide();
515 diff.hide();
511 tr.hide();
516 tr.hide();
512 target.hide();
517 target.hide();
513 });
518 });
514 });
519 });
515
520
516 // Mouse over behavior for comments and line selection
521 // Mouse over behavior for comments and line selection
517
522
518 // Select the line that comes from the url anchor
523 // Select the line that comes from the url anchor
519 // At the time of development, Chrome didn't seem to support jquery's :target
524 // At the time of development, Chrome didn't seem to support jquery's :target
520 // element, so I had to scroll manually
525 // element, so I had to scroll manually
521
526
522 if (location.hash) {
527 if (location.hash) {
523 var result = splitDelimitedHash(location.hash);
528 var result = splitDelimitedHash(location.hash);
524 var loc = result.loc;
529 var loc = result.loc;
525 if (loc.length > 1) {
530 if (loc.length > 1) {
526
531
527 var highlightable_line_tds = [];
532 var highlightable_line_tds = [];
528
533
529 // source code line format
534 // source code line format
530 var page_highlights = loc.substring(
535 var page_highlights = loc.substring(
531 loc.indexOf('#') + 1).split('L');
536 loc.indexOf('#') + 1).split('L');
532
537
533 if (page_highlights.length > 1) {
538 if (page_highlights.length > 1) {
534 var highlight_ranges = page_highlights[1].split(",");
539 var highlight_ranges = page_highlights[1].split(",");
535 var h_lines = [];
540 var h_lines = [];
536 for (var pos in highlight_ranges) {
541 for (var pos in highlight_ranges) {
537 var _range = highlight_ranges[pos].split('-');
542 var _range = highlight_ranges[pos].split('-');
538 if (_range.length === 2) {
543 if (_range.length === 2) {
539 var start = parseInt(_range[0]);
544 var start = parseInt(_range[0]);
540 var end = parseInt(_range[1]);
545 var end = parseInt(_range[1]);
541 if (start < end) {
546 if (start < end) {
542 for (var i = start; i <= end; i++) {
547 for (var i = start; i <= end; i++) {
543 h_lines.push(i);
548 h_lines.push(i);
544 }
549 }
545 }
550 }
546 }
551 }
547 else {
552 else {
548 h_lines.push(parseInt(highlight_ranges[pos]));
553 h_lines.push(parseInt(highlight_ranges[pos]));
549 }
554 }
550 }
555 }
551 for (pos in h_lines) {
556 for (pos in h_lines) {
552 var line_td = $('td.cb-lineno#L' + h_lines[pos]);
557 var line_td = $('td.cb-lineno#L' + h_lines[pos]);
553 if (line_td.length) {
558 if (line_td.length) {
554 highlightable_line_tds.push(line_td);
559 highlightable_line_tds.push(line_td);
555 }
560 }
556 }
561 }
557 }
562 }
558
563
559 // now check a direct id reference (diff page)
564 // now check a direct id reference (diff page)
560 if ($(loc).length && $(loc).hasClass('cb-lineno')) {
565 if ($(loc).length && $(loc).hasClass('cb-lineno')) {
561 highlightable_line_tds.push($(loc));
566 highlightable_line_tds.push($(loc));
562 }
567 }
563 $.each(highlightable_line_tds, function (i, $td) {
568 $.each(highlightable_line_tds, function (i, $td) {
564 $td.addClass('cb-line-selected'); // line number td
569 $td.addClass('cb-line-selected'); // line number td
565 $td.prev().addClass('cb-line-selected'); // line data
570 $td.prev().addClass('cb-line-selected'); // line data
566 $td.next().addClass('cb-line-selected'); // line content
571 $td.next().addClass('cb-line-selected'); // line content
567 });
572 });
568
573
569 if (highlightable_line_tds.length) {
574 if (highlightable_line_tds.length) {
570 var $first_line_td = highlightable_line_tds[0];
575 var $first_line_td = highlightable_line_tds[0];
571 scrollToElement($first_line_td);
576 scrollToElement($first_line_td);
572 $.Topic('/ui/plugins/code/anchor_focus').prepareOrPublish({
577 $.Topic('/ui/plugins/code/anchor_focus').prepareOrPublish({
573 td: $first_line_td,
578 td: $first_line_td,
574 remainder: result.remainder
579 remainder: result.remainder
575 });
580 });
576 }
581 }
577 }
582 }
578 }
583 }
579 collapsableContent();
584 collapsableContent();
580 });
585 });
581
586
582 var feedLifetimeOptions = function(query, initialData){
587 var feedLifetimeOptions = function(query, initialData){
583 var data = {results: []};
588 var data = {results: []};
584 var isQuery = typeof query.term !== 'undefined';
589 var isQuery = typeof query.term !== 'undefined';
585
590
586 var section = _gettext('Lifetime');
591 var section = _gettext('Lifetime');
587 var children = [];
592 var children = [];
588
593
589 //filter results
594 //filter results
590 $.each(initialData.results, function(idx, value) {
595 $.each(initialData.results, function(idx, value) {
591
596
592 if (!isQuery || query.term.length === 0 || value.text.toUpperCase().indexOf(query.term.toUpperCase()) >= 0) {
597 if (!isQuery || query.term.length === 0 || value.text.toUpperCase().indexOf(query.term.toUpperCase()) >= 0) {
593 children.push({
598 children.push({
594 'id': this.id,
599 'id': this.id,
595 'text': this.text
600 'text': this.text
596 })
601 })
597 }
602 }
598
603
599 });
604 });
600 data.results.push({
605 data.results.push({
601 'text': section,
606 'text': section,
602 'children': children
607 'children': children
603 });
608 });
604
609
605 if (isQuery) {
610 if (isQuery) {
606
611
607 var now = moment.utc();
612 var now = moment.utc();
608
613
609 var parseQuery = function(entry, now){
614 var parseQuery = function(entry, now){
610 var fmt = 'DD/MM/YYYY H:mm';
615 var fmt = 'DD/MM/YYYY H:mm';
611 var parsed = moment.utc(entry, fmt);
616 var parsed = moment.utc(entry, fmt);
612 var diffInMin = parsed.diff(now, 'minutes');
617 var diffInMin = parsed.diff(now, 'minutes');
613
618
614 if (diffInMin > 0){
619 if (diffInMin > 0){
615 return {
620 return {
616 id: diffInMin,
621 id: diffInMin,
617 text: parsed.format(fmt)
622 text: parsed.format(fmt)
618 }
623 }
619 } else {
624 } else {
620 return {
625 return {
621 id: undefined,
626 id: undefined,
622 text: parsed.format('DD/MM/YYYY') + ' ' + _gettext('date not in future')
627 text: parsed.format('DD/MM/YYYY') + ' ' + _gettext('date not in future')
623 }
628 }
624 }
629 }
625
630
626
631
627 };
632 };
628
633
629 data.results.push({
634 data.results.push({
630 'text': _gettext('Specified expiration date'),
635 'text': _gettext('Specified expiration date'),
631 'children': [{
636 'children': [{
632 'id': parseQuery(query.term, now).id,
637 'id': parseQuery(query.term, now).id,
633 'text': parseQuery(query.term, now).text
638 'text': parseQuery(query.term, now).text
634 }]
639 }]
635 });
640 });
636 }
641 }
637
642
638 query.callback(data);
643 query.callback(data);
639 };
644 };
640
645
641
646
642 var storeUserSessionAttr = function (key, val) {
647 var storeUserSessionAttr = function (key, val) {
643
648
644 var postData = {
649 var postData = {
645 'key': key,
650 'key': key,
646 'val': val,
651 'val': val,
647 'csrf_token': CSRF_TOKEN
652 'csrf_token': CSRF_TOKEN
648 };
653 };
649
654
650 var success = function(o) {
655 var success = function(o) {
651 return true
656 return true
652 };
657 };
653
658
654 ajaxPOST(pyroutes.url('store_user_session_value'), postData, success);
659 ajaxPOST(pyroutes.url('store_user_session_value'), postData, success);
655 return false;
660 return false;
656 };
661 };
@@ -1,1132 +1,1141 b''
1 ## -*- coding: utf-8 -*-
1 ## -*- coding: utf-8 -*-
2
3 ## base64 filter
4 <%!
5 def base64(text):
6 import base64
7 from rhodecode.lib.helpers import safe_str
8 return base64.encodestring(safe_str(text))
9 %>
10
2 <%inherit file="root.mako"/>
11 <%inherit file="root.mako"/>
3
12
4 <%include file="/ejs_templates/templates.html"/>
13 <%include file="/ejs_templates/templates.html"/>
5
14
6 <div class="outerwrapper">
15 <div class="outerwrapper">
7 <!-- HEADER -->
16 <!-- HEADER -->
8 <div class="header">
17 <div class="header">
9 <div id="header-inner" class="wrapper">
18 <div id="header-inner" class="wrapper">
10 <div id="logo">
19 <div id="logo">
11 <div class="logo-wrapper">
20 <div class="logo-wrapper">
12 <a href="${h.route_path('home')}"><img src="${h.asset('images/rhodecode-logo-white-60x60.png')}" alt="RhodeCode"/></a>
21 <a href="${h.route_path('home')}"><img src="${h.asset('images/rhodecode-logo-white-60x60.png')}" alt="RhodeCode"/></a>
13 </div>
22 </div>
14 % if c.rhodecode_name:
23 % if c.rhodecode_name:
15 <div class="branding">
24 <div class="branding">
16 <a href="${h.route_path('home')}">${h.branding(c.rhodecode_name)}</a>
25 <a href="${h.route_path('home')}">${h.branding(c.rhodecode_name)}</a>
17 </div>
26 </div>
18 % endif
27 % endif
19 </div>
28 </div>
20 <!-- MENU BAR NAV -->
29 <!-- MENU BAR NAV -->
21 ${self.menu_bar_nav()}
30 ${self.menu_bar_nav()}
22 <!-- END MENU BAR NAV -->
31 <!-- END MENU BAR NAV -->
23 </div>
32 </div>
24 </div>
33 </div>
25 ${self.menu_bar_subnav()}
34 ${self.menu_bar_subnav()}
26 <!-- END HEADER -->
35 <!-- END HEADER -->
27
36
28 <!-- CONTENT -->
37 <!-- CONTENT -->
29 <div id="content" class="wrapper">
38 <div id="content" class="wrapper">
30
39
31 <rhodecode-toast id="notifications"></rhodecode-toast>
40 <rhodecode-toast id="notifications"></rhodecode-toast>
32
41
33 <div class="main">
42 <div class="main">
34 ${next.main()}
43 ${next.main()}
35 </div>
44 </div>
36 </div>
45 </div>
37 <!-- END CONTENT -->
46 <!-- END CONTENT -->
38
47
39 </div>
48 </div>
40 <!-- FOOTER -->
49 <!-- FOOTER -->
41 <div id="footer">
50 <div id="footer">
42 <div id="footer-inner" class="title wrapper">
51 <div id="footer-inner" class="title wrapper">
43 <div>
52 <div>
44 <p class="footer-link-right">
53 <p class="footer-link-right">
45 % if c.visual.show_version:
54 % if c.visual.show_version:
46 RhodeCode Enterprise ${c.rhodecode_version} ${c.rhodecode_edition}
55 RhodeCode Enterprise ${c.rhodecode_version} ${c.rhodecode_edition}
47 % endif
56 % endif
48 &copy; 2010-${h.datetime.today().year}, <a href="${h.route_url('rhodecode_official')}" target="_blank">RhodeCode GmbH</a>. All rights reserved.
57 &copy; 2010-${h.datetime.today().year}, <a href="${h.route_url('rhodecode_official')}" target="_blank">RhodeCode GmbH</a>. All rights reserved.
49 % if c.visual.rhodecode_support_url:
58 % if c.visual.rhodecode_support_url:
50 <a href="${c.visual.rhodecode_support_url}" target="_blank">${_('Support')}</a>
59 <a href="${c.visual.rhodecode_support_url}" target="_blank">${_('Support')}</a>
51 % endif
60 % endif
52 </p>
61 </p>
53 <% sid = 'block' if request.GET.get('showrcid') else 'none' %>
62 <% sid = 'block' if request.GET.get('showrcid') else 'none' %>
54 <p class="server-instance" style="display:${sid}">
63 <p class="server-instance" style="display:${sid}">
55 ## display hidden instance ID if specially defined
64 ## display hidden instance ID if specially defined
56 % if c.rhodecode_instanceid:
65 % if c.rhodecode_instanceid:
57 ${_('RhodeCode instance id: {}').format(c.rhodecode_instanceid)}
66 ${_('RhodeCode instance id: {}').format(c.rhodecode_instanceid)}
58 % endif
67 % endif
59 </p>
68 </p>
60 </div>
69 </div>
61 </div>
70 </div>
62 </div>
71 </div>
63
72
64 <!-- END FOOTER -->
73 <!-- END FOOTER -->
65
74
66 ### MAKO DEFS ###
75 ### MAKO DEFS ###
67
76
68 <%def name="menu_bar_subnav()">
77 <%def name="menu_bar_subnav()">
69 </%def>
78 </%def>
70
79
71 <%def name="breadcrumbs(class_='breadcrumbs')">
80 <%def name="breadcrumbs(class_='breadcrumbs')">
72 <div class="${class_}">
81 <div class="${class_}">
73 ${self.breadcrumbs_links()}
82 ${self.breadcrumbs_links()}
74 </div>
83 </div>
75 </%def>
84 </%def>
76
85
77 <%def name="admin_menu(active=None)">
86 <%def name="admin_menu(active=None)">
78 <%
87 <%
79 def is_active(selected):
88 def is_active(selected):
80 if selected == active:
89 if selected == active:
81 return "active"
90 return "active"
82 %>
91 %>
83
92
84 <div id="context-bar">
93 <div id="context-bar">
85 <div class="wrapper">
94 <div class="wrapper">
86 <div class="title">
95 <div class="title">
87 <div class="title-content">
96 <div class="title-content">
88 <div class="title-main">
97 <div class="title-main">
89 % if c.is_super_admin:
98 % if c.is_super_admin:
90 ${_('Super Admin Panel')}
99 ${_('Super Admin Panel')}
91 % else:
100 % else:
92 ${_('Delegated Admin Panel')}
101 ${_('Delegated Admin Panel')}
93 % endif
102 % endif
94 </div>
103 </div>
95 </div>
104 </div>
96 </div>
105 </div>
97
106
98 <ul id="context-pages" class="navigation horizontal-list">
107 <ul id="context-pages" class="navigation horizontal-list">
99
108
100 ## super admin case
109 ## super admin case
101 % if c.is_super_admin:
110 % if c.is_super_admin:
102 <li class="${is_active('audit_logs')}"><a href="${h.route_path('admin_audit_logs')}">${_('Admin audit logs')}</a></li>
111 <li class="${is_active('audit_logs')}"><a href="${h.route_path('admin_audit_logs')}">${_('Admin audit logs')}</a></li>
103 <li class="${is_active('repositories')}"><a href="${h.route_path('repos')}">${_('Repositories')}</a></li>
112 <li class="${is_active('repositories')}"><a href="${h.route_path('repos')}">${_('Repositories')}</a></li>
104 <li class="${is_active('repository_groups')}"><a href="${h.route_path('repo_groups')}">${_('Repository groups')}</a></li>
113 <li class="${is_active('repository_groups')}"><a href="${h.route_path('repo_groups')}">${_('Repository groups')}</a></li>
105 <li class="${is_active('users')}"><a href="${h.route_path('users')}">${_('Users')}</a></li>
114 <li class="${is_active('users')}"><a href="${h.route_path('users')}">${_('Users')}</a></li>
106 <li class="${is_active('user_groups')}"><a href="${h.route_path('user_groups')}">${_('User groups')}</a></li>
115 <li class="${is_active('user_groups')}"><a href="${h.route_path('user_groups')}">${_('User groups')}</a></li>
107 <li class="${is_active('permissions')}"><a href="${h.route_path('admin_permissions_application')}">${_('Permissions')}</a></li>
116 <li class="${is_active('permissions')}"><a href="${h.route_path('admin_permissions_application')}">${_('Permissions')}</a></li>
108 <li class="${is_active('authentication')}"><a href="${h.route_path('auth_home', traverse='')}">${_('Authentication')}</a></li>
117 <li class="${is_active('authentication')}"><a href="${h.route_path('auth_home', traverse='')}">${_('Authentication')}</a></li>
109 <li class="${is_active('integrations')}"><a href="${h.route_path('global_integrations_home')}">${_('Integrations')}</a></li>
118 <li class="${is_active('integrations')}"><a href="${h.route_path('global_integrations_home')}">${_('Integrations')}</a></li>
110 <li class="${is_active('defaults')}"><a href="${h.route_path('admin_defaults_repositories')}">${_('Defaults')}</a></li>
119 <li class="${is_active('defaults')}"><a href="${h.route_path('admin_defaults_repositories')}">${_('Defaults')}</a></li>
111 <li class="${is_active('settings')}"><a href="${h.route_path('admin_settings')}">${_('Settings')}</a></li>
120 <li class="${is_active('settings')}"><a href="${h.route_path('admin_settings')}">${_('Settings')}</a></li>
112
121
113 ## delegated admin
122 ## delegated admin
114 % elif c.is_delegated_admin:
123 % elif c.is_delegated_admin:
115 <%
124 <%
116 repositories=c.auth_user.repositories_admin or c.can_create_repo
125 repositories=c.auth_user.repositories_admin or c.can_create_repo
117 repository_groups=c.auth_user.repository_groups_admin or c.can_create_repo_group
126 repository_groups=c.auth_user.repository_groups_admin or c.can_create_repo_group
118 user_groups=c.auth_user.user_groups_admin or c.can_create_user_group
127 user_groups=c.auth_user.user_groups_admin or c.can_create_user_group
119 %>
128 %>
120
129
121 %if repositories:
130 %if repositories:
122 <li class="${is_active('repositories')} local-admin-repos"><a href="${h.route_path('repos')}">${_('Repositories')}</a></li>
131 <li class="${is_active('repositories')} local-admin-repos"><a href="${h.route_path('repos')}">${_('Repositories')}</a></li>
123 %endif
132 %endif
124 %if repository_groups:
133 %if repository_groups:
125 <li class="${is_active('repository_groups')} local-admin-repo-groups"><a href="${h.route_path('repo_groups')}">${_('Repository groups')}</a></li>
134 <li class="${is_active('repository_groups')} local-admin-repo-groups"><a href="${h.route_path('repo_groups')}">${_('Repository groups')}</a></li>
126 %endif
135 %endif
127 %if user_groups:
136 %if user_groups:
128 <li class="${is_active('user_groups')} local-admin-user-groups"><a href="${h.route_path('user_groups')}">${_('User groups')}</a></li>
137 <li class="${is_active('user_groups')} local-admin-user-groups"><a href="${h.route_path('user_groups')}">${_('User groups')}</a></li>
129 %endif
138 %endif
130 % endif
139 % endif
131 </ul>
140 </ul>
132
141
133 </div>
142 </div>
134 <div class="clear"></div>
143 <div class="clear"></div>
135 </div>
144 </div>
136 </%def>
145 </%def>
137
146
138 <%def name="dt_info_panel(elements)">
147 <%def name="dt_info_panel(elements)">
139 <dl class="dl-horizontal">
148 <dl class="dl-horizontal">
140 %for dt, dd, title, show_items in elements:
149 %for dt, dd, title, show_items in elements:
141 <dt>${dt}:</dt>
150 <dt>${dt}:</dt>
142 <dd title="${h.tooltip(title)}">
151 <dd title="${h.tooltip(title)}">
143 %if callable(dd):
152 %if callable(dd):
144 ## allow lazy evaluation of elements
153 ## allow lazy evaluation of elements
145 ${dd()}
154 ${dd()}
146 %else:
155 %else:
147 ${dd}
156 ${dd}
148 %endif
157 %endif
149 %if show_items:
158 %if show_items:
150 <span class="btn-collapse" data-toggle="item-${h.md5_safe(dt)[:6]}-details">${_('Show More')} </span>
159 <span class="btn-collapse" data-toggle="item-${h.md5_safe(dt)[:6]}-details">${_('Show More')} </span>
151 %endif
160 %endif
152 </dd>
161 </dd>
153
162
154 %if show_items:
163 %if show_items:
155 <div class="collapsable-content" data-toggle="item-${h.md5_safe(dt)[:6]}-details" style="display: none">
164 <div class="collapsable-content" data-toggle="item-${h.md5_safe(dt)[:6]}-details" style="display: none">
156 %for item in show_items:
165 %for item in show_items:
157 <dt></dt>
166 <dt></dt>
158 <dd>${item}</dd>
167 <dd>${item}</dd>
159 %endfor
168 %endfor
160 </div>
169 </div>
161 %endif
170 %endif
162
171
163 %endfor
172 %endfor
164 </dl>
173 </dl>
165 </%def>
174 </%def>
166
175
167 <%def name="tr_info_entry(element)">
176 <%def name="tr_info_entry(element)">
168 <% key, val, title, show_items = element %>
177 <% key, val, title, show_items = element %>
169
178
170 <tr>
179 <tr>
171 <td style="vertical-align: top">${key}</td>
180 <td style="vertical-align: top">${key}</td>
172 <td title="${h.tooltip(title)}">
181 <td title="${h.tooltip(title)}">
173 %if callable(val):
182 %if callable(val):
174 ## allow lazy evaluation of elements
183 ## allow lazy evaluation of elements
175 ${val()}
184 ${val()}
176 %else:
185 %else:
177 ${val}
186 ${val}
178 %endif
187 %endif
179 %if show_items:
188 %if show_items:
180 <div class="collapsable-content" data-toggle="item-${h.md5_safe(val)[:6]}-details" style="display: none">
189 <div class="collapsable-content" data-toggle="item-${h.md5_safe(val)[:6]}-details" style="display: none">
181 % for item in show_items:
190 % for item in show_items:
182 <dt></dt>
191 <dt></dt>
183 <dd>${item}</dd>
192 <dd>${item}</dd>
184 % endfor
193 % endfor
185 </div>
194 </div>
186 %endif
195 %endif
187 </td>
196 </td>
188 <td style="vertical-align: top">
197 <td style="vertical-align: top">
189 %if show_items:
198 %if show_items:
190 <span class="btn-collapse" data-toggle="item-${h.md5_safe(val)[:6]}-details">${_('Show More')} </span>
199 <span class="btn-collapse" data-toggle="item-${h.md5_safe(val)[:6]}-details">${_('Show More')} </span>
191 %endif
200 %endif
192 </td>
201 </td>
193 </tr>
202 </tr>
194
203
195 </%def>
204 </%def>
196
205
197 <%def name="gravatar(email, size=16, tooltip=False, tooltip_alt=None, user=None)">
206 <%def name="gravatar(email, size=16, tooltip=False, tooltip_alt=None, user=None)">
198 <%
207 <%
199 if size > 16:
208 if size > 16:
200 gravatar_class = ['gravatar','gravatar-large']
209 gravatar_class = ['gravatar','gravatar-large']
201 else:
210 else:
202 gravatar_class = ['gravatar']
211 gravatar_class = ['gravatar']
203
212
204 data_hovercard_url = ''
213 data_hovercard_url = ''
205 data_hovercard_alt = tooltip_alt.replace('<', '&lt;').replace('>', '&gt;') if tooltip_alt else ''
214 data_hovercard_alt = tooltip_alt.replace('<', '&lt;').replace('>', '&gt;') if tooltip_alt else ''
206
215
207 if tooltip:
216 if tooltip:
208 gravatar_class += ['tooltip-hovercard']
217 gravatar_class += ['tooltip-hovercard']
209
218
210 if tooltip and user:
219 if tooltip and user:
211 if user.username == h.DEFAULT_USER:
220 if user.username == h.DEFAULT_USER:
212 gravatar_class.pop(-1)
221 gravatar_class.pop(-1)
213 else:
222 else:
214 data_hovercard_url = request.route_path('hovercard_user', user_id=getattr(user, 'user_id', ''))
223 data_hovercard_url = request.route_path('hovercard_user', user_id=getattr(user, 'user_id', ''))
215 gravatar_class = ' '.join(gravatar_class)
224 gravatar_class = ' '.join(gravatar_class)
216
225
217 %>
226 %>
218 <%doc>
227 <%doc>
219 TODO: johbo: For now we serve double size images to make it smooth
228 TODO: johbo: For now we serve double size images to make it smooth
220 for retina. This is how it worked until now. Should be replaced
229 for retina. This is how it worked until now. Should be replaced
221 with a better solution at some point.
230 with a better solution at some point.
222 </%doc>
231 </%doc>
223
232
224 <img class="${gravatar_class}" height="${size}" width="${size}" data-hovercard-url="${data_hovercard_url}" data-hovercard-alt="${data_hovercard_alt}" src="${h.gravatar_url(email, size * 2)}" />
233 <img class="${gravatar_class}" height="${size}" width="${size}" data-hovercard-url="${data_hovercard_url}" data-hovercard-alt="${data_hovercard_alt}" src="${h.gravatar_url(email, size * 2)}" />
225 </%def>
234 </%def>
226
235
227
236
228 <%def name="gravatar_with_user(contact, size=16, show_disabled=False, tooltip=False)">
237 <%def name="gravatar_with_user(contact, size=16, show_disabled=False, tooltip=False)">
229 <%
238 <%
230 email = h.email_or_none(contact)
239 email = h.email_or_none(contact)
231 rc_user = h.discover_user(contact)
240 rc_user = h.discover_user(contact)
232 %>
241 %>
233
242
234 <div class="rc-user">
243 <div class="rc-user">
235 ${self.gravatar(email, size, tooltip=tooltip, tooltip_alt=contact, user=rc_user)}
244 ${self.gravatar(email, size, tooltip=tooltip, tooltip_alt=contact, user=rc_user)}
236 <span class="${('user user-disabled' if show_disabled else 'user')}"> ${h.link_to_user(rc_user or contact)}</span>
245 <span class="${('user user-disabled' if show_disabled else 'user')}"> ${h.link_to_user(rc_user or contact)}</span>
237 </div>
246 </div>
238 </%def>
247 </%def>
239
248
240
249
241 <%def name="user_group_icon(user_group=None, size=16, tooltip=False)">
250 <%def name="user_group_icon(user_group=None, size=16, tooltip=False)">
242 <%
251 <%
243 if (size > 16):
252 if (size > 16):
244 gravatar_class = 'icon-user-group-alt'
253 gravatar_class = 'icon-user-group-alt'
245 else:
254 else:
246 gravatar_class = 'icon-user-group-alt'
255 gravatar_class = 'icon-user-group-alt'
247
256
248 if tooltip:
257 if tooltip:
249 gravatar_class += ' tooltip-hovercard'
258 gravatar_class += ' tooltip-hovercard'
250
259
251 data_hovercard_url = request.route_path('hovercard_user_group', user_group_id=user_group.users_group_id)
260 data_hovercard_url = request.route_path('hovercard_user_group', user_group_id=user_group.users_group_id)
252 %>
261 %>
253 <%doc>
262 <%doc>
254 TODO: johbo: For now we serve double size images to make it smooth
263 TODO: johbo: For now we serve double size images to make it smooth
255 for retina. This is how it worked until now. Should be replaced
264 for retina. This is how it worked until now. Should be replaced
256 with a better solution at some point.
265 with a better solution at some point.
257 </%doc>
266 </%doc>
258
267
259 <i style="font-size: ${size}px" class="${gravatar_class} x-icon-size-${size}" data-hovercard-url="${data_hovercard_url}"></i>
268 <i style="font-size: ${size}px" class="${gravatar_class} x-icon-size-${size}" data-hovercard-url="${data_hovercard_url}"></i>
260 </%def>
269 </%def>
261
270
262 <%def name="repo_page_title(repo_instance)">
271 <%def name="repo_page_title(repo_instance)">
263 <div class="title-content repo-title">
272 <div class="title-content repo-title">
264
273
265 <div class="title-main">
274 <div class="title-main">
266 ## SVN/HG/GIT icons
275 ## SVN/HG/GIT icons
267 %if h.is_hg(repo_instance):
276 %if h.is_hg(repo_instance):
268 <i class="icon-hg"></i>
277 <i class="icon-hg"></i>
269 %endif
278 %endif
270 %if h.is_git(repo_instance):
279 %if h.is_git(repo_instance):
271 <i class="icon-git"></i>
280 <i class="icon-git"></i>
272 %endif
281 %endif
273 %if h.is_svn(repo_instance):
282 %if h.is_svn(repo_instance):
274 <i class="icon-svn"></i>
283 <i class="icon-svn"></i>
275 %endif
284 %endif
276
285
277 ## public/private
286 ## public/private
278 %if repo_instance.private:
287 %if repo_instance.private:
279 <i class="icon-repo-private"></i>
288 <i class="icon-repo-private"></i>
280 %else:
289 %else:
281 <i class="icon-repo-public"></i>
290 <i class="icon-repo-public"></i>
282 %endif
291 %endif
283
292
284 ## repo name with group name
293 ## repo name with group name
285 ${h.breadcrumb_repo_link(repo_instance)}
294 ${h.breadcrumb_repo_link(repo_instance)}
286
295
287 ## Context Actions
296 ## Context Actions
288 <div class="pull-right">
297 <div class="pull-right">
289 %if c.rhodecode_user.username != h.DEFAULT_USER:
298 %if c.rhodecode_user.username != h.DEFAULT_USER:
290 <a href="${h.route_path('atom_feed_home', repo_name=c.rhodecode_db_repo.repo_uid, _query=dict(auth_token=c.rhodecode_user.feed_token))}" title="${_('RSS Feed')}" class="btn btn-sm"><i class="icon-rss-sign"></i>RSS</a>
299 <a href="${h.route_path('atom_feed_home', repo_name=c.rhodecode_db_repo.repo_uid, _query=dict(auth_token=c.rhodecode_user.feed_token))}" title="${_('RSS Feed')}" class="btn btn-sm"><i class="icon-rss-sign"></i>RSS</a>
291
300
292 <a href="#WatchRepo" onclick="toggleFollowingRepo(this, templateContext.repo_id); return false" title="${_('Watch this Repository and actions on it in your personalized journal')}" class="btn btn-sm ${('watching' if c.repository_is_user_following else '')}">
301 <a href="#WatchRepo" onclick="toggleFollowingRepo(this, templateContext.repo_id); return false" title="${_('Watch this Repository and actions on it in your personalized journal')}" class="btn btn-sm ${('watching' if c.repository_is_user_following else '')}">
293 % if c.repository_is_user_following:
302 % if c.repository_is_user_following:
294 <i class="icon-eye-off"></i>${_('Unwatch')}
303 <i class="icon-eye-off"></i>${_('Unwatch')}
295 % else:
304 % else:
296 <i class="icon-eye"></i>${_('Watch')}
305 <i class="icon-eye"></i>${_('Watch')}
297 % endif
306 % endif
298
307
299 </a>
308 </a>
300 %else:
309 %else:
301 <a href="${h.route_path('atom_feed_home', repo_name=c.rhodecode_db_repo.repo_uid)}" title="${_('RSS Feed')}" class="btn btn-sm"><i class="icon-rss-sign"></i>RSS</a>
310 <a href="${h.route_path('atom_feed_home', repo_name=c.rhodecode_db_repo.repo_uid)}" title="${_('RSS Feed')}" class="btn btn-sm"><i class="icon-rss-sign"></i>RSS</a>
302 %endif
311 %endif
303 </div>
312 </div>
304
313
305 </div>
314 </div>
306
315
307 ## FORKED
316 ## FORKED
308 %if repo_instance.fork:
317 %if repo_instance.fork:
309 <p class="discreet">
318 <p class="discreet">
310 <i class="icon-code-fork"></i> ${_('Fork of')}
319 <i class="icon-code-fork"></i> ${_('Fork of')}
311 ${h.link_to_if(c.has_origin_repo_read_perm,repo_instance.fork.repo_name, h.route_path('repo_summary', repo_name=repo_instance.fork.repo_name))}
320 ${h.link_to_if(c.has_origin_repo_read_perm,repo_instance.fork.repo_name, h.route_path('repo_summary', repo_name=repo_instance.fork.repo_name))}
312 </p>
321 </p>
313 %endif
322 %endif
314
323
315 ## IMPORTED FROM REMOTE
324 ## IMPORTED FROM REMOTE
316 %if repo_instance.clone_uri:
325 %if repo_instance.clone_uri:
317 <p class="discreet">
326 <p class="discreet">
318 <i class="icon-code-fork"></i> ${_('Clone from')}
327 <i class="icon-code-fork"></i> ${_('Clone from')}
319 <a href="${h.safe_str(h.hide_credentials(repo_instance.clone_uri))}">${h.hide_credentials(repo_instance.clone_uri)}</a>
328 <a href="${h.safe_str(h.hide_credentials(repo_instance.clone_uri))}">${h.hide_credentials(repo_instance.clone_uri)}</a>
320 </p>
329 </p>
321 %endif
330 %endif
322
331
323 ## LOCKING STATUS
332 ## LOCKING STATUS
324 %if repo_instance.locked[0]:
333 %if repo_instance.locked[0]:
325 <p class="locking_locked discreet">
334 <p class="locking_locked discreet">
326 <i class="icon-repo-lock"></i>
335 <i class="icon-repo-lock"></i>
327 ${_('Repository locked by %(user)s') % {'user': h.person_by_id(repo_instance.locked[0])}}
336 ${_('Repository locked by %(user)s') % {'user': h.person_by_id(repo_instance.locked[0])}}
328 </p>
337 </p>
329 %elif repo_instance.enable_locking:
338 %elif repo_instance.enable_locking:
330 <p class="locking_unlocked discreet">
339 <p class="locking_unlocked discreet">
331 <i class="icon-repo-unlock"></i>
340 <i class="icon-repo-unlock"></i>
332 ${_('Repository not locked. Pull repository to lock it.')}
341 ${_('Repository not locked. Pull repository to lock it.')}
333 </p>
342 </p>
334 %endif
343 %endif
335
344
336 </div>
345 </div>
337 </%def>
346 </%def>
338
347
339 <%def name="repo_menu(active=None)">
348 <%def name="repo_menu(active=None)">
340 <%
349 <%
341 def is_active(selected):
350 def is_active(selected):
342 if selected == active:
351 if selected == active:
343 return "active"
352 return "active"
344 ## determine if we have "any" option available
353 ## determine if we have "any" option available
345 can_lock = h.HasRepoPermissionAny('repository.write','repository.admin')(c.repo_name) and c.rhodecode_db_repo.enable_locking
354 can_lock = h.HasRepoPermissionAny('repository.write','repository.admin')(c.repo_name) and c.rhodecode_db_repo.enable_locking
346 has_actions = can_lock
355 has_actions = can_lock
347
356
348 %>
357 %>
349 % if c.rhodecode_db_repo.archived:
358 % if c.rhodecode_db_repo.archived:
350 <div class="alert alert-warning text-center">
359 <div class="alert alert-warning text-center">
351 <strong>${_('This repository has been archived. It is now read-only.')}</strong>
360 <strong>${_('This repository has been archived. It is now read-only.')}</strong>
352 </div>
361 </div>
353 % endif
362 % endif
354
363
355 <!--- REPO CONTEXT BAR -->
364 <!--- REPO CONTEXT BAR -->
356 <div id="context-bar">
365 <div id="context-bar">
357 <div class="wrapper">
366 <div class="wrapper">
358
367
359 <div class="title">
368 <div class="title">
360 ${self.repo_page_title(c.rhodecode_db_repo)}
369 ${self.repo_page_title(c.rhodecode_db_repo)}
361 </div>
370 </div>
362
371
363 <ul id="context-pages" class="navigation horizontal-list">
372 <ul id="context-pages" class="navigation horizontal-list">
364 <li class="${is_active('summary')}"><a class="menulink" href="${h.route_path('repo_summary', repo_name=c.repo_name)}"><div class="menulabel">${_('Summary')}</div></a></li>
373 <li class="${is_active('summary')}"><a class="menulink" href="${h.route_path('repo_summary', repo_name=c.repo_name)}"><div class="menulabel">${_('Summary')}</div></a></li>
365 <li class="${is_active('commits')}"><a class="menulink" href="${h.route_path('repo_commits', repo_name=c.repo_name)}"><div class="menulabel">${_('Commits')}</div></a></li>
374 <li class="${is_active('commits')}"><a class="menulink" href="${h.route_path('repo_commits', repo_name=c.repo_name)}"><div class="menulabel">${_('Commits')}</div></a></li>
366 <li class="${is_active('files')}"><a class="menulink" href="${h.route_path('repo_files', repo_name=c.repo_name, commit_id=c.rhodecode_db_repo.landing_rev[1], f_path='')}"><div class="menulabel">${_('Files')}</div></a></li>
375 <li class="${is_active('files')}"><a class="menulink" href="${h.route_path('repo_files', repo_name=c.repo_name, commit_id=c.rhodecode_db_repo.landing_rev[1], f_path='')}"><div class="menulabel">${_('Files')}</div></a></li>
367 <li class="${is_active('compare')}"><a class="menulink" href="${h.route_path('repo_compare_select',repo_name=c.repo_name)}"><div class="menulabel">${_('Compare')}</div></a></li>
376 <li class="${is_active('compare')}"><a class="menulink" href="${h.route_path('repo_compare_select',repo_name=c.repo_name)}"><div class="menulabel">${_('Compare')}</div></a></li>
368
377
369 ## TODO: anderson: ideally it would have a function on the scm_instance "enable_pullrequest() and enable_fork()"
378 ## TODO: anderson: ideally it would have a function on the scm_instance "enable_pullrequest() and enable_fork()"
370 %if c.rhodecode_db_repo.repo_type in ['git','hg']:
379 %if c.rhodecode_db_repo.repo_type in ['git','hg']:
371 <li class="${is_active('showpullrequest')}">
380 <li class="${is_active('showpullrequest')}">
372 <a class="menulink" href="${h.route_path('pullrequest_show_all', repo_name=c.repo_name)}" title="${h.tooltip(_('Show Pull Requests for %s') % c.repo_name)}">
381 <a class="menulink" href="${h.route_path('pullrequest_show_all', repo_name=c.repo_name)}" title="${h.tooltip(_('Show Pull Requests for %s') % c.repo_name)}">
373 <div class="menulabel">
382 <div class="menulabel">
374 ${_('Pull Requests')} <span class="menulink-counter">${c.repository_pull_requests}</span>
383 ${_('Pull Requests')} <span class="menulink-counter">${c.repository_pull_requests}</span>
375 </div>
384 </div>
376 </a>
385 </a>
377 </li>
386 </li>
378 %endif
387 %endif
379
388
380 <li class="${is_active('artifacts')}">
389 <li class="${is_active('artifacts')}">
381 <a class="menulink" href="${h.route_path('repo_artifacts_list',repo_name=c.repo_name)}">
390 <a class="menulink" href="${h.route_path('repo_artifacts_list',repo_name=c.repo_name)}">
382 <div class="menulabel">
391 <div class="menulabel">
383 ${_('Artifacts')} <span class="menulink-counter">${c.repository_artifacts}</span>
392 ${_('Artifacts')} <span class="menulink-counter">${c.repository_artifacts}</span>
384 </div>
393 </div>
385 </a>
394 </a>
386 </li>
395 </li>
387
396
388 %if h.HasRepoPermissionAll('repository.admin')(c.repo_name):
397 %if h.HasRepoPermissionAll('repository.admin')(c.repo_name):
389 <li class="${is_active('settings')}"><a class="menulink" href="${h.route_path('edit_repo',repo_name=c.repo_name)}"><div class="menulabel">${_('Repository Settings')}</div></a></li>
398 <li class="${is_active('settings')}"><a class="menulink" href="${h.route_path('edit_repo',repo_name=c.repo_name)}"><div class="menulabel">${_('Repository Settings')}</div></a></li>
390 %endif
399 %endif
391
400
392 <li class="${is_active('options')}">
401 <li class="${is_active('options')}">
393 % if has_actions:
402 % if has_actions:
394 <a class="menulink dropdown">
403 <a class="menulink dropdown">
395 <div class="menulabel">${_('Options')}<div class="show_more"></div></div>
404 <div class="menulabel">${_('Options')}<div class="show_more"></div></div>
396 </a>
405 </a>
397 <ul class="submenu">
406 <ul class="submenu">
398 %if can_lock:
407 %if can_lock:
399 %if c.rhodecode_db_repo.locked[0]:
408 %if c.rhodecode_db_repo.locked[0]:
400 <li><a class="locking_del" href="${h.route_path('repo_edit_toggle_locking',repo_name=c.repo_name)}">${_('Unlock Repository')}</a></li>
409 <li><a class="locking_del" href="${h.route_path('repo_edit_toggle_locking',repo_name=c.repo_name)}">${_('Unlock Repository')}</a></li>
401 %else:
410 %else:
402 <li><a class="locking_add" href="${h.route_path('repo_edit_toggle_locking',repo_name=c.repo_name)}">${_('Lock Repository')}</a></li>
411 <li><a class="locking_add" href="${h.route_path('repo_edit_toggle_locking',repo_name=c.repo_name)}">${_('Lock Repository')}</a></li>
403 %endif
412 %endif
404 %endif
413 %endif
405 </ul>
414 </ul>
406 % else:
415 % else:
407 <a class="menulink disabled">
416 <a class="menulink disabled">
408 <div class="menulabel">${_('Options')}<div class="show_more"></div></div>
417 <div class="menulabel">${_('Options')}<div class="show_more"></div></div>
409 </a>
418 </a>
410 % endif
419 % endif
411 </li>
420 </li>
412
421
413 </ul>
422 </ul>
414 </div>
423 </div>
415 <div class="clear"></div>
424 <div class="clear"></div>
416 </div>
425 </div>
417
426
418 <!--- REPO END CONTEXT BAR -->
427 <!--- REPO END CONTEXT BAR -->
419
428
420 </%def>
429 </%def>
421
430
422 <%def name="repo_group_page_title(repo_group_instance)">
431 <%def name="repo_group_page_title(repo_group_instance)">
423 <div class="title-content">
432 <div class="title-content">
424 <div class="title-main">
433 <div class="title-main">
425 ## Repository Group icon
434 ## Repository Group icon
426 <i class="icon-repo-group"></i>
435 <i class="icon-repo-group"></i>
427
436
428 ## repo name with group name
437 ## repo name with group name
429 ${h.breadcrumb_repo_group_link(repo_group_instance)}
438 ${h.breadcrumb_repo_group_link(repo_group_instance)}
430 </div>
439 </div>
431
440
432 <%namespace name="dt" file="/data_table/_dt_elements.mako"/>
441 <%namespace name="dt" file="/data_table/_dt_elements.mako"/>
433 <div class="repo-group-desc discreet">
442 <div class="repo-group-desc discreet">
434 ${dt.repo_group_desc(repo_group_instance.description_safe, repo_group_instance.personal, c.visual.stylify_metatags)}
443 ${dt.repo_group_desc(repo_group_instance.description_safe, repo_group_instance.personal, c.visual.stylify_metatags)}
435 </div>
444 </div>
436
445
437 </div>
446 </div>
438 </%def>
447 </%def>
439
448
440
449
441 <%def name="repo_group_menu(active=None)">
450 <%def name="repo_group_menu(active=None)">
442 <%
451 <%
443 def is_active(selected):
452 def is_active(selected):
444 if selected == active:
453 if selected == active:
445 return "active"
454 return "active"
446
455
447 gr_name = c.repo_group.group_name if c.repo_group else None
456 gr_name = c.repo_group.group_name if c.repo_group else None
448 # create repositories with write permission on group is set to true
457 # create repositories with write permission on group is set to true
449 group_admin = h.HasRepoGroupPermissionAny('group.admin')(gr_name, 'group admin index page')
458 group_admin = h.HasRepoGroupPermissionAny('group.admin')(gr_name, 'group admin index page')
450
459
451 %>
460 %>
452
461
453
462
454 <!--- REPO GROUP CONTEXT BAR -->
463 <!--- REPO GROUP CONTEXT BAR -->
455 <div id="context-bar">
464 <div id="context-bar">
456 <div class="wrapper">
465 <div class="wrapper">
457 <div class="title">
466 <div class="title">
458 ${self.repo_group_page_title(c.repo_group)}
467 ${self.repo_group_page_title(c.repo_group)}
459 </div>
468 </div>
460
469
461 <ul id="context-pages" class="navigation horizontal-list">
470 <ul id="context-pages" class="navigation horizontal-list">
462 <li class="${is_active('home')}">
471 <li class="${is_active('home')}">
463 <a class="menulink" href="${h.route_path('repo_group_home', repo_group_name=c.repo_group.group_name)}"><div class="menulabel">${_('Group Home')}</div></a>
472 <a class="menulink" href="${h.route_path('repo_group_home', repo_group_name=c.repo_group.group_name)}"><div class="menulabel">${_('Group Home')}</div></a>
464 </li>
473 </li>
465 % if c.is_super_admin or group_admin:
474 % if c.is_super_admin or group_admin:
466 <li class="${is_active('settings')}">
475 <li class="${is_active('settings')}">
467 <a class="menulink" href="${h.route_path('edit_repo_group',repo_group_name=c.repo_group.group_name)}" title="${_('You have admin right to this group, and can edit it')}"><div class="menulabel">${_('Group Settings')}</div></a>
476 <a class="menulink" href="${h.route_path('edit_repo_group',repo_group_name=c.repo_group.group_name)}" title="${_('You have admin right to this group, and can edit it')}"><div class="menulabel">${_('Group Settings')}</div></a>
468 </li>
477 </li>
469 % endif
478 % endif
470
479
471 </ul>
480 </ul>
472 </div>
481 </div>
473 <div class="clear"></div>
482 <div class="clear"></div>
474 </div>
483 </div>
475
484
476 <!--- REPO GROUP CONTEXT BAR -->
485 <!--- REPO GROUP CONTEXT BAR -->
477
486
478 </%def>
487 </%def>
479
488
480
489
481 <%def name="usermenu(active=False)">
490 <%def name="usermenu(active=False)">
482 <%
491 <%
483 not_anonymous = c.rhodecode_user.username != h.DEFAULT_USER
492 not_anonymous = c.rhodecode_user.username != h.DEFAULT_USER
484
493
485 gr_name = c.repo_group.group_name if (hasattr(c, 'repo_group') and c.repo_group) else None
494 gr_name = c.repo_group.group_name if (hasattr(c, 'repo_group') and c.repo_group) else None
486 # create repositories with write permission on group is set to true
495 # create repositories with write permission on group is set to true
487
496
488 can_fork = c.is_super_admin or h.HasPermissionAny('hg.fork.repository')()
497 can_fork = c.is_super_admin or h.HasPermissionAny('hg.fork.repository')()
489 create_on_write = h.HasPermissionAny('hg.create.write_on_repogroup.true')()
498 create_on_write = h.HasPermissionAny('hg.create.write_on_repogroup.true')()
490 group_write = h.HasRepoGroupPermissionAny('group.write')(gr_name, 'can write into group index page')
499 group_write = h.HasRepoGroupPermissionAny('group.write')(gr_name, 'can write into group index page')
491 group_admin = h.HasRepoGroupPermissionAny('group.admin')(gr_name, 'group admin index page')
500 group_admin = h.HasRepoGroupPermissionAny('group.admin')(gr_name, 'group admin index page')
492
501
493 can_create_repos = c.is_super_admin or c.can_create_repo
502 can_create_repos = c.is_super_admin or c.can_create_repo
494 can_create_repo_groups = c.is_super_admin or c.can_create_repo_group
503 can_create_repo_groups = c.is_super_admin or c.can_create_repo_group
495
504
496 can_create_repos_in_group = c.is_super_admin or group_admin or (group_write and create_on_write)
505 can_create_repos_in_group = c.is_super_admin or group_admin or (group_write and create_on_write)
497 can_create_repo_groups_in_group = c.is_super_admin or group_admin
506 can_create_repo_groups_in_group = c.is_super_admin or group_admin
498 %>
507 %>
499
508
500 % if not_anonymous:
509 % if not_anonymous:
501 <%
510 <%
502 default_target_group = dict()
511 default_target_group = dict()
503 if c.rhodecode_user.personal_repo_group:
512 if c.rhodecode_user.personal_repo_group:
504 default_target_group = dict(parent_group=c.rhodecode_user.personal_repo_group.group_id)
513 default_target_group = dict(parent_group=c.rhodecode_user.personal_repo_group.group_id)
505 %>
514 %>
506
515
507 ## create action
516 ## create action
508 <li>
517 <li>
509 <a href="#create-actions" onclick="return false;" class="menulink childs">
518 <a href="#create-actions" onclick="return false;" class="menulink childs">
510 <i class="icon-plus-circled"></i>
519 <i class="icon-plus-circled"></i>
511 </a>
520 </a>
512
521
513 <div class="action-menu submenu">
522 <div class="action-menu submenu">
514
523
515 <ol>
524 <ol>
516 ## scope of within a repository
525 ## scope of within a repository
517 % if hasattr(c, 'rhodecode_db_repo') and c.rhodecode_db_repo:
526 % if hasattr(c, 'rhodecode_db_repo') and c.rhodecode_db_repo:
518 <li class="submenu-title">${_('This Repository')}</li>
527 <li class="submenu-title">${_('This Repository')}</li>
519 <li>
528 <li>
520 <a href="${h.route_path('pullrequest_new',repo_name=c.repo_name)}">${_('Create Pull Request')}</a>
529 <a href="${h.route_path('pullrequest_new',repo_name=c.repo_name)}">${_('Create Pull Request')}</a>
521 </li>
530 </li>
522 % if can_fork:
531 % if can_fork:
523 <li>
532 <li>
524 <a href="${h.route_path('repo_fork_new',repo_name=c.repo_name,_query=default_target_group)}">${_('Fork this repository')}</a>
533 <a href="${h.route_path('repo_fork_new',repo_name=c.repo_name,_query=default_target_group)}">${_('Fork this repository')}</a>
525 </li>
534 </li>
526 % endif
535 % endif
527 % endif
536 % endif
528
537
529 ## scope of within repository groups
538 ## scope of within repository groups
530 % if hasattr(c, 'repo_group') and c.repo_group and (can_create_repos_in_group or can_create_repo_groups_in_group):
539 % if hasattr(c, 'repo_group') and c.repo_group and (can_create_repos_in_group or can_create_repo_groups_in_group):
531 <li class="submenu-title">${_('This Repository Group')}</li>
540 <li class="submenu-title">${_('This Repository Group')}</li>
532
541
533 % if can_create_repos_in_group:
542 % if can_create_repos_in_group:
534 <li>
543 <li>
535 <a href="${h.route_path('repo_new',_query=default_target_group)}">${_('New Repository')}</a>
544 <a href="${h.route_path('repo_new',_query=default_target_group)}">${_('New Repository')}</a>
536 </li>
545 </li>
537 % endif
546 % endif
538
547
539 % if can_create_repo_groups_in_group:
548 % if can_create_repo_groups_in_group:
540 <li>
549 <li>
541 <a href="${h.route_path('repo_group_new',_query=default_target_group)}">${_(u'New Repository Group')}</a>
550 <a href="${h.route_path('repo_group_new',_query=default_target_group)}">${_(u'New Repository Group')}</a>
542 </li>
551 </li>
543 % endif
552 % endif
544 % endif
553 % endif
545
554
546 ## personal group
555 ## personal group
547 % if c.rhodecode_user.personal_repo_group:
556 % if c.rhodecode_user.personal_repo_group:
548 <li class="submenu-title">Personal Group</li>
557 <li class="submenu-title">Personal Group</li>
549
558
550 <li>
559 <li>
551 <a href="${h.route_path('repo_new',_query=dict(parent_group=c.rhodecode_user.personal_repo_group.group_id))}" >${_('New Repository')} </a>
560 <a href="${h.route_path('repo_new',_query=dict(parent_group=c.rhodecode_user.personal_repo_group.group_id))}" >${_('New Repository')} </a>
552 </li>
561 </li>
553
562
554 <li>
563 <li>
555 <a href="${h.route_path('repo_group_new',_query=dict(parent_group=c.rhodecode_user.personal_repo_group.group_id))}">${_('New Repository Group')} </a>
564 <a href="${h.route_path('repo_group_new',_query=dict(parent_group=c.rhodecode_user.personal_repo_group.group_id))}">${_('New Repository Group')} </a>
556 </li>
565 </li>
557 % endif
566 % endif
558
567
559 ## Global actions
568 ## Global actions
560 <li class="submenu-title">RhodeCode</li>
569 <li class="submenu-title">RhodeCode</li>
561 % if can_create_repos:
570 % if can_create_repos:
562 <li>
571 <li>
563 <a href="${h.route_path('repo_new')}" >${_('New Repository')}</a>
572 <a href="${h.route_path('repo_new')}" >${_('New Repository')}</a>
564 </li>
573 </li>
565 % endif
574 % endif
566
575
567 % if can_create_repo_groups:
576 % if can_create_repo_groups:
568 <li>
577 <li>
569 <a href="${h.route_path('repo_group_new')}" >${_(u'New Repository Group')}</a>
578 <a href="${h.route_path('repo_group_new')}" >${_(u'New Repository Group')}</a>
570 </li>
579 </li>
571 % endif
580 % endif
572
581
573 <li>
582 <li>
574 <a href="${h.route_path('gists_new')}">${_(u'New Gist')}</a>
583 <a href="${h.route_path('gists_new')}">${_(u'New Gist')}</a>
575 </li>
584 </li>
576
585
577 </ol>
586 </ol>
578
587
579 </div>
588 </div>
580 </li>
589 </li>
581
590
582 ## notifications
591 ## notifications
583 <li>
592 <li>
584 <a class="${('empty' if c.unread_notifications == 0 else '')}" href="${h.route_path('notifications_show_all')}">
593 <a class="${('empty' if c.unread_notifications == 0 else '')}" href="${h.route_path('notifications_show_all')}">
585 ${c.unread_notifications}
594 ${c.unread_notifications}
586 </a>
595 </a>
587 </li>
596 </li>
588 % endif
597 % endif
589
598
590 ## USER MENU
599 ## USER MENU
591 <li id="quick_login_li" class="${'active' if active else ''}">
600 <li id="quick_login_li" class="${'active' if active else ''}">
592 % if c.rhodecode_user.username == h.DEFAULT_USER:
601 % if c.rhodecode_user.username == h.DEFAULT_USER:
593 <a id="quick_login_link" class="menulink childs" href="${h.route_path('login', _query={'came_from': h.current_route_path(request)})}">
602 <a id="quick_login_link" class="menulink childs" href="${h.route_path('login', _query={'came_from': h.current_route_path(request)})}">
594 ${gravatar(c.rhodecode_user.email, 20)}
603 ${gravatar(c.rhodecode_user.email, 20)}
595 <span class="user">
604 <span class="user">
596 <span>${_('Sign in')}</span>
605 <span>${_('Sign in')}</span>
597 </span>
606 </span>
598 </a>
607 </a>
599 % else:
608 % else:
600 ## logged in user
609 ## logged in user
601 <a id="quick_login_link" class="menulink childs">
610 <a id="quick_login_link" class="menulink childs">
602 ${gravatar(c.rhodecode_user.email, 20)}
611 ${gravatar(c.rhodecode_user.email, 20)}
603 <span class="user">
612 <span class="user">
604 <span class="menu_link_user">${c.rhodecode_user.username}</span>
613 <span class="menu_link_user">${c.rhodecode_user.username}</span>
605 <div class="show_more"></div>
614 <div class="show_more"></div>
606 </span>
615 </span>
607 </a>
616 </a>
608 ## subnav with menu for logged in user
617 ## subnav with menu for logged in user
609 <div class="user-menu submenu">
618 <div class="user-menu submenu">
610 <div id="quick_login">
619 <div id="quick_login">
611 %if c.rhodecode_user.username != h.DEFAULT_USER:
620 %if c.rhodecode_user.username != h.DEFAULT_USER:
612 <div class="">
621 <div class="">
613 <div class="big_gravatar">${gravatar(c.rhodecode_user.email, 48)}</div>
622 <div class="big_gravatar">${gravatar(c.rhodecode_user.email, 48)}</div>
614 <div class="full_name">${c.rhodecode_user.full_name_or_username}</div>
623 <div class="full_name">${c.rhodecode_user.full_name_or_username}</div>
615 <div class="email">${c.rhodecode_user.email}</div>
624 <div class="email">${c.rhodecode_user.email}</div>
616 </div>
625 </div>
617 <div class="">
626 <div class="">
618 <ol class="links">
627 <ol class="links">
619 <li>${h.link_to(_(u'My account'),h.route_path('my_account_profile'))}</li>
628 <li>${h.link_to(_(u'My account'),h.route_path('my_account_profile'))}</li>
620 % if c.rhodecode_user.personal_repo_group:
629 % if c.rhodecode_user.personal_repo_group:
621 <li>${h.link_to(_(u'My personal group'), h.route_path('repo_group_home', repo_group_name=c.rhodecode_user.personal_repo_group.group_name))}</li>
630 <li>${h.link_to(_(u'My personal group'), h.route_path('repo_group_home', repo_group_name=c.rhodecode_user.personal_repo_group.group_name))}</li>
622 % endif
631 % endif
623 <li>${h.link_to(_(u'Pull Requests'), h.route_path('my_account_pullrequests'))}</li>
632 <li>${h.link_to(_(u'Pull Requests'), h.route_path('my_account_pullrequests'))}</li>
624
633
625 % if c.debug_style:
634 % if c.debug_style:
626 <li>
635 <li>
627 <a class="menulink" title="${_('Style')}" href="${h.route_path('debug_style_home')}">
636 <a class="menulink" title="${_('Style')}" href="${h.route_path('debug_style_home')}">
628 <div class="menulabel">${_('[Style]')}</div>
637 <div class="menulabel">${_('[Style]')}</div>
629 </a>
638 </a>
630 </li>
639 </li>
631 % endif
640 % endif
632
641
633 ## bookmark-items
642 ## bookmark-items
634 <li class="bookmark-items">
643 <li class="bookmark-items">
635 ${_('Bookmarks')}
644 ${_('Bookmarks')}
636 <div class="pull-right">
645 <div class="pull-right">
637 <a href="${h.route_path('my_account_bookmarks')}">
646 <a href="${h.route_path('my_account_bookmarks')}">
638
647
639 <i class="icon-cog"></i>
648 <i class="icon-cog"></i>
640 </a>
649 </a>
641 </div>
650 </div>
642 </li>
651 </li>
643 % if not c.bookmark_items:
652 % if not c.bookmark_items:
644 <li>
653 <li>
645 <a href="${h.route_path('my_account_bookmarks')}">${_('No Bookmarks yet.')}</a>
654 <a href="${h.route_path('my_account_bookmarks')}">${_('No Bookmarks yet.')}</a>
646 </li>
655 </li>
647 % endif
656 % endif
648 % for item in c.bookmark_items:
657 % for item in c.bookmark_items:
649 <li>
658 <li>
650 % if item.repository:
659 % if item.repository:
651 <div>
660 <div>
652 <a class="bookmark-item" href="${h.route_path('my_account_goto_bookmark', bookmark_id=item.position)}">
661 <a class="bookmark-item" href="${h.route_path('my_account_goto_bookmark', bookmark_id=item.position)}">
653 <code>${item.position}</code>
662 <code>${item.position}</code>
654 % if item.repository.repo_type == 'hg':
663 % if item.repository.repo_type == 'hg':
655 <i class="icon-hg" title="${_('Repository')}" style="font-size: 16px"></i>
664 <i class="icon-hg" title="${_('Repository')}" style="font-size: 16px"></i>
656 % elif item.repository.repo_type == 'git':
665 % elif item.repository.repo_type == 'git':
657 <i class="icon-git" title="${_('Repository')}" style="font-size: 16px"></i>
666 <i class="icon-git" title="${_('Repository')}" style="font-size: 16px"></i>
658 % elif item.repository.repo_type == 'svn':
667 % elif item.repository.repo_type == 'svn':
659 <i class="icon-svn" title="${_('Repository')}" style="font-size: 16px"></i>
668 <i class="icon-svn" title="${_('Repository')}" style="font-size: 16px"></i>
660 % endif
669 % endif
661 ${(item.title or h.shorter(item.repository.repo_name, 30))}
670 ${(item.title or h.shorter(item.repository.repo_name, 30))}
662 </a>
671 </a>
663 </div>
672 </div>
664 % elif item.repository_group:
673 % elif item.repository_group:
665 <div>
674 <div>
666 <a class="bookmark-item" href="${h.route_path('my_account_goto_bookmark', bookmark_id=item.position)}">
675 <a class="bookmark-item" href="${h.route_path('my_account_goto_bookmark', bookmark_id=item.position)}">
667 <code>${item.position}</code>
676 <code>${item.position}</code>
668 <i class="icon-repo-group" title="${_('Repository group')}" style="font-size: 14px"></i>
677 <i class="icon-repo-group" title="${_('Repository group')}" style="font-size: 14px"></i>
669 ${(item.title or h.shorter(item.repository_group.group_name, 30))}
678 ${(item.title or h.shorter(item.repository_group.group_name, 30))}
670 </a>
679 </a>
671 </div>
680 </div>
672 % else:
681 % else:
673 <a class="bookmark-item" href="${h.route_path('my_account_goto_bookmark', bookmark_id=item.position)}">
682 <a class="bookmark-item" href="${h.route_path('my_account_goto_bookmark', bookmark_id=item.position)}">
674 <code>${item.position}</code>
683 <code>${item.position}</code>
675 ${item.title}
684 ${item.title}
676 </a>
685 </a>
677 % endif
686 % endif
678 </li>
687 </li>
679 % endfor
688 % endfor
680
689
681 <li class="logout">
690 <li class="logout">
682 ${h.secure_form(h.route_path('logout'), request=request)}
691 ${h.secure_form(h.route_path('logout'), request=request)}
683 ${h.submit('log_out', _(u'Sign Out'),class_="btn btn-primary")}
692 ${h.submit('log_out', _(u'Sign Out'),class_="btn btn-primary")}
684 ${h.end_form()}
693 ${h.end_form()}
685 </li>
694 </li>
686 </ol>
695 </ol>
687 </div>
696 </div>
688 %endif
697 %endif
689 </div>
698 </div>
690 </div>
699 </div>
691
700
692 % endif
701 % endif
693 </li>
702 </li>
694 </%def>
703 </%def>
695
704
696 <%def name="menu_items(active=None)">
705 <%def name="menu_items(active=None)">
697 <%
706 <%
698 def is_active(selected):
707 def is_active(selected):
699 if selected == active:
708 if selected == active:
700 return "active"
709 return "active"
701 return ""
710 return ""
702 %>
711 %>
703
712
704 <ul id="quick" class="main_nav navigation horizontal-list">
713 <ul id="quick" class="main_nav navigation horizontal-list">
705 ## notice box for important system messages
714 ## notice box for important system messages
706 <li style="display: none">
715 <li style="display: none">
707 <a class="notice-box" href="#openNotice" onclick="return false">
716 <a class="notice-box" href="#openNotice" onclick="return false">
708 <div class="menulabel-notice" >
717 <div class="menulabel-notice" >
709 0
718 0
710 </div>
719 </div>
711 </a>
720 </a>
712 </li>
721 </li>
713
722
714 ## Main filter
723 ## Main filter
715 <li>
724 <li>
716 <div class="menulabel main_filter_box">
725 <div class="menulabel main_filter_box">
717 <div class="main_filter_input_box">
726 <div class="main_filter_input_box">
718 <ul class="searchItems">
727 <ul class="searchItems">
719
728
720 % if c.template_context['search_context']['repo_id']:
729 % if c.template_context['search_context']['repo_id']:
721 <li class="searchTag searchTagFilter searchTagHidable" >
730 <li class="searchTag searchTagFilter searchTagHidable" >
722 ##<a href="${h.route_path('search_repo',repo_name=c.template_context['search_context']['repo_name'])}">
731 ##<a href="${h.route_path('search_repo',repo_name=c.template_context['search_context']['repo_name'])}">
723 <span class="tag">
732 <span class="tag">
724 This repo
733 This repo
725 <a href="#removeGoToFilter" onclick="removeGoToFilter(); return false"><i class="icon-cancel-circled"></i></a>
734 <a href="#removeGoToFilter" onclick="removeGoToFilter(); return false"><i class="icon-cancel-circled"></i></a>
726 </span>
735 </span>
727 ##</a>
736 ##</a>
728 </li>
737 </li>
729 % elif c.template_context['search_context']['repo_group_id']:
738 % elif c.template_context['search_context']['repo_group_id']:
730 <li class="searchTag searchTagFilter searchTagHidable">
739 <li class="searchTag searchTagFilter searchTagHidable">
731 ##<a href="${h.route_path('search_repo_group',repo_group_name=c.template_context['search_context']['repo_group_name'])}">
740 ##<a href="${h.route_path('search_repo_group',repo_group_name=c.template_context['search_context']['repo_group_name'])}">
732 <span class="tag">
741 <span class="tag">
733 This group
742 This group
734 <a href="#removeGoToFilter" onclick="removeGoToFilter(); return false"><i class="icon-cancel-circled"></i></a>
743 <a href="#removeGoToFilter" onclick="removeGoToFilter(); return false"><i class="icon-cancel-circled"></i></a>
735 </span>
744 </span>
736 ##</a>
745 ##</a>
737 </li>
746 </li>
738 % endif
747 % endif
739
748
740 <li class="searchTagInput">
749 <li class="searchTagInput">
741 <input class="main_filter_input" id="main_filter" size="25" type="text" name="main_filter" placeholder="${_('search / go to...')}" value="" />
750 <input class="main_filter_input" id="main_filter" size="25" type="text" name="main_filter" placeholder="${_('search / go to...')}" value="" />
742 </li>
751 </li>
743 <li class="searchTag searchTagHelp">
752 <li class="searchTag searchTagHelp">
744 <a href="#showFilterHelp" onclick="showMainFilterBox(); return false">?</a>
753 <a href="#showFilterHelp" onclick="showMainFilterBox(); return false">?</a>
745 </li>
754 </li>
746 </ul>
755 </ul>
747 </div>
756 </div>
748 </div>
757 </div>
749
758
750 <div id="main_filter_help" style="display: none">
759 <div id="main_filter_help" style="display: none">
751 - Use '/' key to quickly access this field.
760 - Use '/' key to quickly access this field.
752
761
753 - Enter a name of repository, or repository group for quick search.
762 - Enter a name of repository, or repository group for quick search.
754
763
755 - Prefix query to allow special search:
764 - Prefix query to allow special search:
756
765
757 user:admin, to search for usernames, always global
766 user:admin, to search for usernames, always global
758
767
759 user_group:devops, to search for user groups, always global
768 user_group:devops, to search for user groups, always global
760
769
761 commit:efced4, to search for commits, scoped to repositories or groups
770 commit:efced4, to search for commits, scoped to repositories or groups
762
771
763 file:models.py, to search for file paths, scoped to repositories or groups
772 file:models.py, to search for file paths, scoped to repositories or groups
764
773
765 % if c.template_context['search_context']['repo_id']:
774 % if c.template_context['search_context']['repo_id']:
766 For advanced full text search visit: <a href="${h.route_path('search_repo',repo_name=c.template_context['search_context']['repo_name'])}">repository search</a>
775 For advanced full text search visit: <a href="${h.route_path('search_repo',repo_name=c.template_context['search_context']['repo_name'])}">repository search</a>
767 % elif c.template_context['search_context']['repo_group_id']:
776 % elif c.template_context['search_context']['repo_group_id']:
768 For advanced full text search visit: <a href="${h.route_path('search_repo_group',repo_group_name=c.template_context['search_context']['repo_group_name'])}">repository group search</a>
777 For advanced full text search visit: <a href="${h.route_path('search_repo_group',repo_group_name=c.template_context['search_context']['repo_group_name'])}">repository group search</a>
769 % else:
778 % else:
770 For advanced full text search visit: <a href="${h.route_path('search')}">global search</a>
779 For advanced full text search visit: <a href="${h.route_path('search')}">global search</a>
771 % endif
780 % endif
772 </div>
781 </div>
773 </li>
782 </li>
774
783
775 ## ROOT MENU
784 ## ROOT MENU
776 <li class="${is_active('home')}">
785 <li class="${is_active('home')}">
777 <a class="menulink" title="${_('Home')}" href="${h.route_path('home')}">
786 <a class="menulink" title="${_('Home')}" href="${h.route_path('home')}">
778 <div class="menulabel">${_('Home')}</div>
787 <div class="menulabel">${_('Home')}</div>
779 </a>
788 </a>
780 </li>
789 </li>
781
790
782 %if c.rhodecode_user.username != h.DEFAULT_USER:
791 %if c.rhodecode_user.username != h.DEFAULT_USER:
783 <li class="${is_active('journal')}">
792 <li class="${is_active('journal')}">
784 <a class="menulink" title="${_('Show activity journal')}" href="${h.route_path('journal')}">
793 <a class="menulink" title="${_('Show activity journal')}" href="${h.route_path('journal')}">
785 <div class="menulabel">${_('Journal')}</div>
794 <div class="menulabel">${_('Journal')}</div>
786 </a>
795 </a>
787 </li>
796 </li>
788 %else:
797 %else:
789 <li class="${is_active('journal')}">
798 <li class="${is_active('journal')}">
790 <a class="menulink" title="${_('Show Public activity journal')}" href="${h.route_path('journal_public')}">
799 <a class="menulink" title="${_('Show Public activity journal')}" href="${h.route_path('journal_public')}">
791 <div class="menulabel">${_('Public journal')}</div>
800 <div class="menulabel">${_('Public journal')}</div>
792 </a>
801 </a>
793 </li>
802 </li>
794 %endif
803 %endif
795
804
796 <li class="${is_active('gists')}">
805 <li class="${is_active('gists')}">
797 <a class="menulink childs" title="${_('Show Gists')}" href="${h.route_path('gists_show')}">
806 <a class="menulink childs" title="${_('Show Gists')}" href="${h.route_path('gists_show')}">
798 <div class="menulabel">${_('Gists')}</div>
807 <div class="menulabel">${_('Gists')}</div>
799 </a>
808 </a>
800 </li>
809 </li>
801
810
802 % if c.is_super_admin or c.is_delegated_admin:
811 % if c.is_super_admin or c.is_delegated_admin:
803 <li class="${is_active('admin')}">
812 <li class="${is_active('admin')}">
804 <a class="menulink childs" title="${_('Admin settings')}" href="${h.route_path('admin_home')}">
813 <a class="menulink childs" title="${_('Admin settings')}" href="${h.route_path('admin_home')}">
805 <div class="menulabel">${_('Admin')} </div>
814 <div class="menulabel">${_('Admin')} </div>
806 </a>
815 </a>
807 </li>
816 </li>
808 % endif
817 % endif
809
818
810 ## render extra user menu
819 ## render extra user menu
811 ${usermenu(active=(active=='my_account'))}
820 ${usermenu(active=(active=='my_account'))}
812
821
813 </ul>
822 </ul>
814
823
815 <script type="text/javascript">
824 <script type="text/javascript">
816 var visualShowPublicIcon = "${c.visual.show_public_icon}" == "True";
825 var visualShowPublicIcon = "${c.visual.show_public_icon}" == "True";
817
826
818 var formatRepoResult = function(result, container, query, escapeMarkup) {
827 var formatRepoResult = function(result, container, query, escapeMarkup) {
819 return function(data, escapeMarkup) {
828 return function(data, escapeMarkup) {
820 if (!data.repo_id){
829 if (!data.repo_id){
821 return data.text; // optgroup text Repositories
830 return data.text; // optgroup text Repositories
822 }
831 }
823
832
824 var tmpl = '';
833 var tmpl = '';
825 var repoType = data['repo_type'];
834 var repoType = data['repo_type'];
826 var repoName = data['text'];
835 var repoName = data['text'];
827
836
828 if(data && data.type == 'repo'){
837 if(data && data.type == 'repo'){
829 if(repoType === 'hg'){
838 if(repoType === 'hg'){
830 tmpl += '<i class="icon-hg"></i> ';
839 tmpl += '<i class="icon-hg"></i> ';
831 }
840 }
832 else if(repoType === 'git'){
841 else if(repoType === 'git'){
833 tmpl += '<i class="icon-git"></i> ';
842 tmpl += '<i class="icon-git"></i> ';
834 }
843 }
835 else if(repoType === 'svn'){
844 else if(repoType === 'svn'){
836 tmpl += '<i class="icon-svn"></i> ';
845 tmpl += '<i class="icon-svn"></i> ';
837 }
846 }
838 if(data['private']){
847 if(data['private']){
839 tmpl += '<i class="icon-lock" ></i> ';
848 tmpl += '<i class="icon-lock" ></i> ';
840 }
849 }
841 else if(visualShowPublicIcon){
850 else if(visualShowPublicIcon){
842 tmpl += '<i class="icon-unlock-alt"></i> ';
851 tmpl += '<i class="icon-unlock-alt"></i> ';
843 }
852 }
844 }
853 }
845 tmpl += escapeMarkup(repoName);
854 tmpl += escapeMarkup(repoName);
846 return tmpl;
855 return tmpl;
847
856
848 }(result, escapeMarkup);
857 }(result, escapeMarkup);
849 };
858 };
850
859
851 var formatRepoGroupResult = function(result, container, query, escapeMarkup) {
860 var formatRepoGroupResult = function(result, container, query, escapeMarkup) {
852 return function(data, escapeMarkup) {
861 return function(data, escapeMarkup) {
853 if (!data.repo_group_id){
862 if (!data.repo_group_id){
854 return data.text; // optgroup text Repositories
863 return data.text; // optgroup text Repositories
855 }
864 }
856
865
857 var tmpl = '';
866 var tmpl = '';
858 var repoGroupName = data['text'];
867 var repoGroupName = data['text'];
859
868
860 if(data){
869 if(data){
861
870
862 tmpl += '<i class="icon-repo-group"></i> ';
871 tmpl += '<i class="icon-repo-group"></i> ';
863
872
864 }
873 }
865 tmpl += escapeMarkup(repoGroupName);
874 tmpl += escapeMarkup(repoGroupName);
866 return tmpl;
875 return tmpl;
867
876
868 }(result, escapeMarkup);
877 }(result, escapeMarkup);
869 };
878 };
870
879
871 var escapeRegExChars = function (value) {
880 var escapeRegExChars = function (value) {
872 return value.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&");
881 return value.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&");
873 };
882 };
874
883
875 var getRepoIcon = function(repo_type) {
884 var getRepoIcon = function(repo_type) {
876 if (repo_type === 'hg') {
885 if (repo_type === 'hg') {
877 return '<i class="icon-hg"></i> ';
886 return '<i class="icon-hg"></i> ';
878 }
887 }
879 else if (repo_type === 'git') {
888 else if (repo_type === 'git') {
880 return '<i class="icon-git"></i> ';
889 return '<i class="icon-git"></i> ';
881 }
890 }
882 else if (repo_type === 'svn') {
891 else if (repo_type === 'svn') {
883 return '<i class="icon-svn"></i> ';
892 return '<i class="icon-svn"></i> ';
884 }
893 }
885 return ''
894 return ''
886 };
895 };
887
896
888 var autocompleteMainFilterFormatResult = function (data, value, org_formatter) {
897 var autocompleteMainFilterFormatResult = function (data, value, org_formatter) {
889
898
890 if (value.split(':').length === 2) {
899 if (value.split(':').length === 2) {
891 value = value.split(':')[1]
900 value = value.split(':')[1]
892 }
901 }
893
902
894 var searchType = data['type'];
903 var searchType = data['type'];
895 var searchSubType = data['subtype'];
904 var searchSubType = data['subtype'];
896 var valueDisplay = data['value_display'];
905 var valueDisplay = data['value_display'];
897
906
898 var pattern = '(' + escapeRegExChars(value) + ')';
907 var pattern = '(' + escapeRegExChars(value) + ')';
899
908
900 valueDisplay = Select2.util.escapeMarkup(valueDisplay);
909 valueDisplay = Select2.util.escapeMarkup(valueDisplay);
901
910
902 // highlight match
911 // highlight match
903 if (searchType != 'text') {
912 if (searchType != 'text') {
904 valueDisplay = valueDisplay.replace(new RegExp(pattern, 'gi'), '<strong>$1<\/strong>');
913 valueDisplay = valueDisplay.replace(new RegExp(pattern, 'gi'), '<strong>$1<\/strong>');
905 }
914 }
906
915
907 var icon = '';
916 var icon = '';
908
917
909 if (searchType === 'hint') {
918 if (searchType === 'hint') {
910 icon += '<i class="icon-repo-group"></i> ';
919 icon += '<i class="icon-repo-group"></i> ';
911 }
920 }
912 // full text search/hints
921 // full text search/hints
913 else if (searchType === 'search') {
922 else if (searchType === 'search') {
914 icon += '<i class="icon-more"></i> ';
923 icon += '<i class="icon-more"></i> ';
915 if (searchSubType !== undefined && searchSubType == 'repo') {
924 if (searchSubType !== undefined && searchSubType == 'repo') {
916 valueDisplay += '<div class="pull-right tag">repository</div>';
925 valueDisplay += '<div class="pull-right tag">repository</div>';
917 }
926 }
918 else if (searchSubType !== undefined && searchSubType == 'repo_group') {
927 else if (searchSubType !== undefined && searchSubType == 'repo_group') {
919 valueDisplay += '<div class="pull-right tag">repo group</div>';
928 valueDisplay += '<div class="pull-right tag">repo group</div>';
920 }
929 }
921 }
930 }
922 // repository
931 // repository
923 else if (searchType === 'repo') {
932 else if (searchType === 'repo') {
924
933
925 var repoIcon = getRepoIcon(data['repo_type']);
934 var repoIcon = getRepoIcon(data['repo_type']);
926 icon += repoIcon;
935 icon += repoIcon;
927
936
928 if (data['private']) {
937 if (data['private']) {
929 icon += '<i class="icon-lock" ></i> ';
938 icon += '<i class="icon-lock" ></i> ';
930 }
939 }
931 else if (visualShowPublicIcon) {
940 else if (visualShowPublicIcon) {
932 icon += '<i class="icon-unlock-alt"></i> ';
941 icon += '<i class="icon-unlock-alt"></i> ';
933 }
942 }
934 }
943 }
935 // repository groups
944 // repository groups
936 else if (searchType === 'repo_group') {
945 else if (searchType === 'repo_group') {
937 icon += '<i class="icon-repo-group"></i> ';
946 icon += '<i class="icon-repo-group"></i> ';
938 }
947 }
939 // user group
948 // user group
940 else if (searchType === 'user_group') {
949 else if (searchType === 'user_group') {
941 icon += '<i class="icon-group"></i> ';
950 icon += '<i class="icon-group"></i> ';
942 }
951 }
943 // user
952 // user
944 else if (searchType === 'user') {
953 else if (searchType === 'user') {
945 icon += '<img class="gravatar" src="{0}"/>'.format(data['icon_link']);
954 icon += '<img class="gravatar" src="{0}"/>'.format(data['icon_link']);
946 }
955 }
947 // commit
956 // commit
948 else if (searchType === 'commit') {
957 else if (searchType === 'commit') {
949 var repo_data = data['repo_data'];
958 var repo_data = data['repo_data'];
950 var repoIcon = getRepoIcon(repo_data['repository_type']);
959 var repoIcon = getRepoIcon(repo_data['repository_type']);
951 if (repoIcon) {
960 if (repoIcon) {
952 icon += repoIcon;
961 icon += repoIcon;
953 } else {
962 } else {
954 icon += '<i class="icon-tag"></i>';
963 icon += '<i class="icon-tag"></i>';
955 }
964 }
956 }
965 }
957 // file
966 // file
958 else if (searchType === 'file') {
967 else if (searchType === 'file') {
959 var repo_data = data['repo_data'];
968 var repo_data = data['repo_data'];
960 var repoIcon = getRepoIcon(repo_data['repository_type']);
969 var repoIcon = getRepoIcon(repo_data['repository_type']);
961 if (repoIcon) {
970 if (repoIcon) {
962 icon += repoIcon;
971 icon += repoIcon;
963 } else {
972 } else {
964 icon += '<i class="icon-tag"></i>';
973 icon += '<i class="icon-tag"></i>';
965 }
974 }
966 }
975 }
967 // generic text
976 // generic text
968 else if (searchType === 'text') {
977 else if (searchType === 'text') {
969 icon = '';
978 icon = '';
970 }
979 }
971
980
972 var tmpl = '<div class="ac-container-wrap">{0}{1}</div>';
981 var tmpl = '<div class="ac-container-wrap">{0}{1}</div>';
973 return tmpl.format(icon, valueDisplay);
982 return tmpl.format(icon, valueDisplay);
974 };
983 };
975
984
976 var handleSelect = function(element, suggestion) {
985 var handleSelect = function(element, suggestion) {
977 if (suggestion.type === "hint") {
986 if (suggestion.type === "hint") {
978 // we skip action
987 // we skip action
979 $('#main_filter').focus();
988 $('#main_filter').focus();
980 }
989 }
981 else if (suggestion.type === "text") {
990 else if (suggestion.type === "text") {
982 // we skip action
991 // we skip action
983 $('#main_filter').focus();
992 $('#main_filter').focus();
984
993
985 } else {
994 } else {
986 window.location = suggestion['url'];
995 window.location = suggestion['url'];
987 }
996 }
988 };
997 };
989
998
990 var autocompleteMainFilterResult = function (suggestion, originalQuery, queryLowerCase) {
999 var autocompleteMainFilterResult = function (suggestion, originalQuery, queryLowerCase) {
991 if (queryLowerCase.split(':').length === 2) {
1000 if (queryLowerCase.split(':').length === 2) {
992 queryLowerCase = queryLowerCase.split(':')[1]
1001 queryLowerCase = queryLowerCase.split(':')[1]
993 }
1002 }
994 if (suggestion.type === "text") {
1003 if (suggestion.type === "text") {
995 // special case we don't want to "skip" display for
1004 // special case we don't want to "skip" display for
996 return true
1005 return true
997 }
1006 }
998 return suggestion.value_display.toLowerCase().indexOf(queryLowerCase) !== -1;
1007 return suggestion.value_display.toLowerCase().indexOf(queryLowerCase) !== -1;
999 };
1008 };
1000
1009
1001 var cleanContext = {
1010 var cleanContext = {
1002 repo_view_type: null,
1011 repo_view_type: null,
1003
1012
1004 repo_id: null,
1013 repo_id: null,
1005 repo_name: "",
1014 repo_name: "",
1006
1015
1007 repo_group_id: null,
1016 repo_group_id: null,
1008 repo_group_name: null
1017 repo_group_name: null
1009 };
1018 };
1010 var removeGoToFilter = function () {
1019 var removeGoToFilter = function () {
1011 $('.searchTagHidable').hide();
1020 $('.searchTagHidable').hide();
1012 $('#main_filter').autocomplete(
1021 $('#main_filter').autocomplete(
1013 'setOptions', {params:{search_context: cleanContext}});
1022 'setOptions', {params:{search_context: cleanContext}});
1014 };
1023 };
1015
1024
1016 $('#main_filter').autocomplete({
1025 $('#main_filter').autocomplete({
1017 serviceUrl: pyroutes.url('goto_switcher_data'),
1026 serviceUrl: pyroutes.url('goto_switcher_data'),
1018 params: {
1027 params: {
1019 "search_context": templateContext.search_context
1028 "search_context": templateContext.search_context
1020 },
1029 },
1021 minChars:2,
1030 minChars:2,
1022 maxHeight:400,
1031 maxHeight:400,
1023 deferRequestBy: 300, //miliseconds
1032 deferRequestBy: 300, //miliseconds
1024 tabDisabled: true,
1033 tabDisabled: true,
1025 autoSelectFirst: false,
1034 autoSelectFirst: false,
1026 containerClass: 'autocomplete-qfilter-suggestions',
1035 containerClass: 'autocomplete-qfilter-suggestions',
1027 formatResult: autocompleteMainFilterFormatResult,
1036 formatResult: autocompleteMainFilterFormatResult,
1028 lookupFilter: autocompleteMainFilterResult,
1037 lookupFilter: autocompleteMainFilterResult,
1029 onSelect: function (element, suggestion) {
1038 onSelect: function (element, suggestion) {
1030 handleSelect(element, suggestion);
1039 handleSelect(element, suggestion);
1031 return false;
1040 return false;
1032 },
1041 },
1033 onSearchError: function (element, query, jqXHR, textStatus, errorThrown) {
1042 onSearchError: function (element, query, jqXHR, textStatus, errorThrown) {
1034 if (jqXHR !== 'abort') {
1043 if (jqXHR !== 'abort') {
1035 alert("Error during search.\nError code: {0}".format(textStatus));
1044 alert("Error during search.\nError code: {0}".format(textStatus));
1036 window.location = '';
1045 window.location = '';
1037 }
1046 }
1038 }
1047 }
1039 });
1048 });
1040
1049
1041 showMainFilterBox = function () {
1050 showMainFilterBox = function () {
1042 $('#main_filter_help').toggle();
1051 $('#main_filter_help').toggle();
1043 };
1052 };
1044
1053
1045 $('#main_filter').on('keydown.autocomplete', function (e) {
1054 $('#main_filter').on('keydown.autocomplete', function (e) {
1046
1055
1047 var BACKSPACE = 8;
1056 var BACKSPACE = 8;
1048 var el = $(e.currentTarget);
1057 var el = $(e.currentTarget);
1049 if(e.which === BACKSPACE){
1058 if(e.which === BACKSPACE){
1050 var inputVal = el.val();
1059 var inputVal = el.val();
1051 if (inputVal === ""){
1060 if (inputVal === ""){
1052 removeGoToFilter()
1061 removeGoToFilter()
1053 }
1062 }
1054 }
1063 }
1055 });
1064 });
1056
1065
1057 </script>
1066 </script>
1058 <script src="${h.asset('js/rhodecode/base/keyboard-bindings.js', ver=c.rhodecode_version_hash)}"></script>
1067 <script src="${h.asset('js/rhodecode/base/keyboard-bindings.js', ver=c.rhodecode_version_hash)}"></script>
1059 </%def>
1068 </%def>
1060
1069
1061 <div class="modal" id="help_kb" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
1070 <div class="modal" id="help_kb" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
1062 <div class="modal-dialog">
1071 <div class="modal-dialog">
1063 <div class="modal-content">
1072 <div class="modal-content">
1064 <div class="modal-header">
1073 <div class="modal-header">
1065 <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
1074 <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
1066 <h4 class="modal-title" id="myModalLabel">${_('Keyboard shortcuts')}</h4>
1075 <h4 class="modal-title" id="myModalLabel">${_('Keyboard shortcuts')}</h4>
1067 </div>
1076 </div>
1068 <div class="modal-body">
1077 <div class="modal-body">
1069 <div class="block-left">
1078 <div class="block-left">
1070 <table class="keyboard-mappings">
1079 <table class="keyboard-mappings">
1071 <tbody>
1080 <tbody>
1072 <tr>
1081 <tr>
1073 <th></th>
1082 <th></th>
1074 <th>${_('Site-wide shortcuts')}</th>
1083 <th>${_('Site-wide shortcuts')}</th>
1075 </tr>
1084 </tr>
1076 <%
1085 <%
1077 elems = [
1086 elems = [
1078 ('/', 'Use quick search box'),
1087 ('/', 'Use quick search box'),
1079 ('g h', 'Goto home page'),
1088 ('g h', 'Goto home page'),
1080 ('g g', 'Goto my private gists page'),
1089 ('g g', 'Goto my private gists page'),
1081 ('g G', 'Goto my public gists page'),
1090 ('g G', 'Goto my public gists page'),
1082 ('g 0-9', 'Goto bookmarked items from 0-9'),
1091 ('g 0-9', 'Goto bookmarked items from 0-9'),
1083 ('n r', 'New repository page'),
1092 ('n r', 'New repository page'),
1084 ('n g', 'New gist page'),
1093 ('n g', 'New gist page'),
1085 ]
1094 ]
1086 %>
1095 %>
1087 %for key, desc in elems:
1096 %for key, desc in elems:
1088 <tr>
1097 <tr>
1089 <td class="keys">
1098 <td class="keys">
1090 <span class="key tag">${key}</span>
1099 <span class="key tag">${key}</span>
1091 </td>
1100 </td>
1092 <td>${desc}</td>
1101 <td>${desc}</td>
1093 </tr>
1102 </tr>
1094 %endfor
1103 %endfor
1095 </tbody>
1104 </tbody>
1096 </table>
1105 </table>
1097 </div>
1106 </div>
1098 <div class="block-left">
1107 <div class="block-left">
1099 <table class="keyboard-mappings">
1108 <table class="keyboard-mappings">
1100 <tbody>
1109 <tbody>
1101 <tr>
1110 <tr>
1102 <th></th>
1111 <th></th>
1103 <th>${_('Repositories')}</th>
1112 <th>${_('Repositories')}</th>
1104 </tr>
1113 </tr>
1105 <%
1114 <%
1106 elems = [
1115 elems = [
1107 ('g s', 'Goto summary page'),
1116 ('g s', 'Goto summary page'),
1108 ('g c', 'Goto changelog page'),
1117 ('g c', 'Goto changelog page'),
1109 ('g f', 'Goto files page'),
1118 ('g f', 'Goto files page'),
1110 ('g F', 'Goto files page with file search activated'),
1119 ('g F', 'Goto files page with file search activated'),
1111 ('g p', 'Goto pull requests page'),
1120 ('g p', 'Goto pull requests page'),
1112 ('g o', 'Goto repository settings'),
1121 ('g o', 'Goto repository settings'),
1113 ('g O', 'Goto repository access permissions settings'),
1122 ('g O', 'Goto repository access permissions settings'),
1114 ]
1123 ]
1115 %>
1124 %>
1116 %for key, desc in elems:
1125 %for key, desc in elems:
1117 <tr>
1126 <tr>
1118 <td class="keys">
1127 <td class="keys">
1119 <span class="key tag">${key}</span>
1128 <span class="key tag">${key}</span>
1120 </td>
1129 </td>
1121 <td>${desc}</td>
1130 <td>${desc}</td>
1122 </tr>
1131 </tr>
1123 %endfor
1132 %endfor
1124 </tbody>
1133 </tbody>
1125 </table>
1134 </table>
1126 </div>
1135 </div>
1127 </div>
1136 </div>
1128 <div class="modal-footer">
1137 <div class="modal-footer">
1129 </div>
1138 </div>
1130 </div><!-- /.modal-content -->
1139 </div><!-- /.modal-content -->
1131 </div><!-- /.modal-dialog -->
1140 </div><!-- /.modal-dialog -->
1132 </div><!-- /.modal -->
1141 </div><!-- /.modal -->
General Comments 0
You need to be logged in to leave comments. Login now