##// END OF EJS Templates
use placeholders in qfilter, not the ugly JS logic
marcink -
r3665:690a955b beta
parent child Browse files
Show More
@@ -1,2174 +1,2170 b''
1 1 /**
2 2 RhodeCode JS Files
3 3 **/
4 4
5 5 if (typeof console == "undefined" || typeof console.log == "undefined"){
6 6 console = { log: function() {} }
7 7 }
8 8
9 9
10 10 var str_repeat = function(i, m) {
11 11 for (var o = []; m > 0; o[--m] = i);
12 12 return o.join('');
13 13 };
14 14
15 15 /**
16 16 * INJECT .format function into String
17 17 * Usage: "My name is {0} {1}".format("Johny","Bravo")
18 18 * Return "My name is Johny Bravo"
19 19 * Inspired by https://gist.github.com/1049426
20 20 */
21 21 String.prototype.format = function() {
22 22
23 23 function format() {
24 24 var str = this;
25 25 var len = arguments.length+1;
26 26 var safe = undefined;
27 27 var arg = undefined;
28 28
29 29 // For each {0} {1} {n...} replace with the argument in that position. If
30 30 // the argument is an object or an array it will be stringified to JSON.
31 31 for (var i=0; i < len; arg = arguments[i++]) {
32 32 safe = typeof arg === 'object' ? JSON.stringify(arg) : arg;
33 33 str = str.replace(RegExp('\\{'+(i-1)+'\\}', 'g'), safe);
34 34 }
35 35 return str;
36 36 }
37 37
38 38 // Save a reference of what may already exist under the property native.
39 39 // Allows for doing something like: if("".format.native) { /* use native */ }
40 40 format.native = String.prototype.format;
41 41
42 42 // Replace the prototype property
43 43 return format;
44 44
45 45 }();
46 46
47 47 String.prototype.strip = function(char) {
48 48 if(char === undefined){
49 49 char = '\\s';
50 50 }
51 51 return this.replace(new RegExp('^'+char+'+|'+char+'+$','g'), '');
52 52 }
53 53 String.prototype.lstrip = function(char) {
54 54 if(char === undefined){
55 55 char = '\\s';
56 56 }
57 57 return this.replace(new RegExp('^'+char+'+'),'');
58 58 }
59 59 String.prototype.rstrip = function(char) {
60 60 if(char === undefined){
61 61 char = '\\s';
62 62 }
63 63 return this.replace(new RegExp(''+char+'+$'),'');
64 64 }
65 65
66 66
67 67 if(!Array.prototype.indexOf) {
68 68 Array.prototype.indexOf = function(needle) {
69 69 for(var i = 0; i < this.length; i++) {
70 70 if(this[i] === needle) {
71 71 return i;
72 72 }
73 73 }
74 74 return -1;
75 75 };
76 76 }
77 77
78 78 // IE(CRAP) doesn't support previousElementSibling
79 79 var prevElementSibling = function( el ) {
80 80 if( el.previousElementSibling ) {
81 81 return el.previousElementSibling;
82 82 } else {
83 83 while( el = el.previousSibling ) {
84 84 if( el.nodeType === 1 ) return el;
85 85 }
86 86 }
87 87 }
88 88
89 89 /**
90 90 * SmartColorGenerator
91 91 *
92 92 *usage::
93 93 * var CG = new ColorGenerator();
94 94 * var col = CG.getColor(key); //returns array of RGB
95 95 * 'rgb({0})'.format(col.join(',')
96 96 *
97 97 * @returns {ColorGenerator}
98 98 */
99 99 var ColorGenerator = function(){
100 100 this.GOLDEN_RATIO = 0.618033988749895;
101 101 this.CURRENT_RATIO = 0.22717784590367374 // this can be random
102 102 this.HSV_1 = 0.75;//saturation
103 103 this.HSV_2 = 0.95;
104 104 this.color;
105 105 this.cacheColorMap = {};
106 106 };
107 107
108 108 ColorGenerator.prototype = {
109 109 getColor:function(key){
110 110 if(this.cacheColorMap[key] !== undefined){
111 111 return this.cacheColorMap[key];
112 112 }
113 113 else{
114 114 this.cacheColorMap[key] = this.generateColor();
115 115 return this.cacheColorMap[key];
116 116 }
117 117 },
118 118 _hsvToRgb:function(h,s,v){
119 119 if (s == 0.0)
120 120 return [v, v, v];
121 121 i = parseInt(h * 6.0)
122 122 f = (h * 6.0) - i
123 123 p = v * (1.0 - s)
124 124 q = v * (1.0 - s * f)
125 125 t = v * (1.0 - s * (1.0 - f))
126 126 i = i % 6
127 127 if (i == 0)
128 128 return [v, t, p]
129 129 if (i == 1)
130 130 return [q, v, p]
131 131 if (i == 2)
132 132 return [p, v, t]
133 133 if (i == 3)
134 134 return [p, q, v]
135 135 if (i == 4)
136 136 return [t, p, v]
137 137 if (i == 5)
138 138 return [v, p, q]
139 139 },
140 140 generateColor:function(){
141 141 this.CURRENT_RATIO = this.CURRENT_RATIO+this.GOLDEN_RATIO;
142 142 this.CURRENT_RATIO = this.CURRENT_RATIO %= 1;
143 143 HSV_tuple = [this.CURRENT_RATIO, this.HSV_1, this.HSV_2]
144 144 RGB_tuple = this._hsvToRgb(HSV_tuple[0],HSV_tuple[1],HSV_tuple[2]);
145 145 function toRgb(v){
146 146 return ""+parseInt(v*256)
147 147 }
148 148 return [toRgb(RGB_tuple[0]),toRgb(RGB_tuple[1]),toRgb(RGB_tuple[2])];
149 149
150 150 }
151 151 }
152 152
153 153 /**
154 154 * PyRoutesJS
155 155 *
156 156 * Usage pyroutes.url('mark_error_fixed',{"error_id":error_id}) // /mark_error_fixed/<error_id>
157 157 */
158 158 var pyroutes = (function() {
159 159 // access global map defined in special file pyroutes
160 160 var matchlist = PROUTES_MAP;
161 161 var sprintf = (function() {
162 162 function get_type(variable) {
163 163 return Object.prototype.toString.call(variable).slice(8, -1).toLowerCase();
164 164 }
165 165 function str_repeat(input, multiplier) {
166 166 for (var output = []; multiplier > 0; output[--multiplier] = input) {/* do nothing */}
167 167 return output.join('');
168 168 }
169 169
170 170 var str_format = function() {
171 171 if (!str_format.cache.hasOwnProperty(arguments[0])) {
172 172 str_format.cache[arguments[0]] = str_format.parse(arguments[0]);
173 173 }
174 174 return str_format.format.call(null, str_format.cache[arguments[0]], arguments);
175 175 };
176 176
177 177 str_format.format = function(parse_tree, argv) {
178 178 var cursor = 1, tree_length = parse_tree.length, node_type = '', arg, output = [], i, k, match, pad, pad_character, pad_length;
179 179 for (i = 0; i < tree_length; i++) {
180 180 node_type = get_type(parse_tree[i]);
181 181 if (node_type === 'string') {
182 182 output.push(parse_tree[i]);
183 183 }
184 184 else if (node_type === 'array') {
185 185 match = parse_tree[i]; // convenience purposes only
186 186 if (match[2]) { // keyword argument
187 187 arg = argv[cursor];
188 188 for (k = 0; k < match[2].length; k++) {
189 189 if (!arg.hasOwnProperty(match[2][k])) {
190 190 throw(sprintf('[sprintf] property "%s" does not exist', match[2][k]));
191 191 }
192 192 arg = arg[match[2][k]];
193 193 }
194 194 }
195 195 else if (match[1]) { // positional argument (explicit)
196 196 arg = argv[match[1]];
197 197 }
198 198 else { // positional argument (implicit)
199 199 arg = argv[cursor++];
200 200 }
201 201
202 202 if (/[^s]/.test(match[8]) && (get_type(arg) != 'number')) {
203 203 throw(sprintf('[sprintf] expecting number but found %s', get_type(arg)));
204 204 }
205 205 switch (match[8]) {
206 206 case 'b': arg = arg.toString(2); break;
207 207 case 'c': arg = String.fromCharCode(arg); break;
208 208 case 'd': arg = parseInt(arg, 10); break;
209 209 case 'e': arg = match[7] ? arg.toExponential(match[7]) : arg.toExponential(); break;
210 210 case 'f': arg = match[7] ? parseFloat(arg).toFixed(match[7]) : parseFloat(arg); break;
211 211 case 'o': arg = arg.toString(8); break;
212 212 case 's': arg = ((arg = String(arg)) && match[7] ? arg.substring(0, match[7]) : arg); break;
213 213 case 'u': arg = Math.abs(arg); break;
214 214 case 'x': arg = arg.toString(16); break;
215 215 case 'X': arg = arg.toString(16).toUpperCase(); break;
216 216 }
217 217 arg = (/[def]/.test(match[8]) && match[3] && arg >= 0 ? '+'+ arg : arg);
218 218 pad_character = match[4] ? match[4] == '0' ? '0' : match[4].charAt(1) : ' ';
219 219 pad_length = match[6] - String(arg).length;
220 220 pad = match[6] ? str_repeat(pad_character, pad_length) : '';
221 221 output.push(match[5] ? arg + pad : pad + arg);
222 222 }
223 223 }
224 224 return output.join('');
225 225 };
226 226
227 227 str_format.cache = {};
228 228
229 229 str_format.parse = function(fmt) {
230 230 var _fmt = fmt, match = [], parse_tree = [], arg_names = 0;
231 231 while (_fmt) {
232 232 if ((match = /^[^\x25]+/.exec(_fmt)) !== null) {
233 233 parse_tree.push(match[0]);
234 234 }
235 235 else if ((match = /^\x25{2}/.exec(_fmt)) !== null) {
236 236 parse_tree.push('%');
237 237 }
238 238 else if ((match = /^\x25(?:([1-9]\d*)\$|\(([^\)]+)\))?(\+)?(0|'[^$])?(-)?(\d+)?(?:\.(\d+))?([b-fosuxX])/.exec(_fmt)) !== null) {
239 239 if (match[2]) {
240 240 arg_names |= 1;
241 241 var field_list = [], replacement_field = match[2], field_match = [];
242 242 if ((field_match = /^([a-z_][a-z_\d]*)/i.exec(replacement_field)) !== null) {
243 243 field_list.push(field_match[1]);
244 244 while ((replacement_field = replacement_field.substring(field_match[0].length)) !== '') {
245 245 if ((field_match = /^\.([a-z_][a-z_\d]*)/i.exec(replacement_field)) !== null) {
246 246 field_list.push(field_match[1]);
247 247 }
248 248 else if ((field_match = /^\[(\d+)\]/.exec(replacement_field)) !== null) {
249 249 field_list.push(field_match[1]);
250 250 }
251 251 else {
252 252 throw('[sprintf] huh?');
253 253 }
254 254 }
255 255 }
256 256 else {
257 257 throw('[sprintf] huh?');
258 258 }
259 259 match[2] = field_list;
260 260 }
261 261 else {
262 262 arg_names |= 2;
263 263 }
264 264 if (arg_names === 3) {
265 265 throw('[sprintf] mixing positional and named placeholders is not (yet) supported');
266 266 }
267 267 parse_tree.push(match);
268 268 }
269 269 else {
270 270 throw('[sprintf] huh?');
271 271 }
272 272 _fmt = _fmt.substring(match[0].length);
273 273 }
274 274 return parse_tree;
275 275 };
276 276
277 277 return str_format;
278 278 })();
279 279
280 280 var vsprintf = function(fmt, argv) {
281 281 argv.unshift(fmt);
282 282 return sprintf.apply(null, argv);
283 283 };
284 284 return {
285 285 'url': function(route_name, params) {
286 286 var result = route_name;
287 287 if (typeof(params) != 'object'){
288 288 params = {};
289 289 }
290 290 if (matchlist.hasOwnProperty(route_name)) {
291 291 var route = matchlist[route_name];
292 292 // param substitution
293 293 for(var i=0; i < route[1].length; i++) {
294 294
295 295 if (!params.hasOwnProperty(route[1][i]))
296 296 throw new Error(route[1][i] + ' missing in "' + route_name + '" route generation');
297 297 }
298 298 result = sprintf(route[0], params);
299 299
300 300 var ret = [];
301 301 //extra params => GET
302 302 for(param in params){
303 303 if (route[1].indexOf(param) == -1){
304 304 ret.push(encodeURIComponent(param) + "=" + encodeURIComponent(params[param]));
305 305 }
306 306 }
307 307 var _parts = ret.join("&");
308 308 if(_parts){
309 309 result = result +'?'+ _parts
310 310 }
311 311 }
312 312
313 313 return result;
314 314 },
315 315 'register': function(route_name, route_tmpl, req_params) {
316 316 if (typeof(req_params) != 'object') {
317 317 req_params = [];
318 318 }
319 319 //fix escape
320 320 route_tmpl = unescape(route_tmpl);
321 321 keys = [];
322 322 for (o in req_params){
323 323 keys.push(req_params[o])
324 324 }
325 325 matchlist[route_name] = [
326 326 route_tmpl,
327 327 keys
328 328 ]
329 329 },
330 330 '_routes': function(){
331 331 return matchlist;
332 332 }
333 333 }
334 334 })();
335 335
336 336
337 337
338 338 /**
339 339 * GLOBAL YUI Shortcuts
340 340 */
341 341 var YUC = YAHOO.util.Connect;
342 342 var YUD = YAHOO.util.Dom;
343 343 var YUE = YAHOO.util.Event;
344 344 var YUQ = YAHOO.util.Selector.query;
345 345
346 346 // defines if push state is enabled for this browser ?
347 347 var push_state_enabled = Boolean(
348 348 window.history && window.history.pushState && window.history.replaceState
349 349 && !( /* disable for versions of iOS before version 4.3 (8F190) */
350 350 (/ Mobile\/([1-7][a-z]|(8([abcde]|f(1[0-8]))))/i).test(navigator.userAgent)
351 351 /* disable for the mercury iOS browser, or at least older versions of the webkit engine */
352 352 || (/AppleWebKit\/5([0-2]|3[0-2])/i).test(navigator.userAgent)
353 353 )
354 354 );
355 355
356 356 var _run_callbacks = function(callbacks){
357 357 if (callbacks !== undefined){
358 358 var _l = callbacks.length;
359 359 for (var i=0;i<_l;i++){
360 360 var func = callbacks[i];
361 361 if(typeof(func)=='function'){
362 362 try{
363 363 func();
364 364 }catch (err){};
365 365 }
366 366 }
367 367 }
368 368 }
369 369
370 370 /**
371 371 * Partial Ajax Implementation
372 372 *
373 373 * @param url: defines url to make partial request
374 374 * @param container: defines id of container to input partial result
375 375 * @param s_call: success callback function that takes o as arg
376 376 * o.tId
377 377 * o.status
378 378 * o.statusText
379 379 * o.getResponseHeader[ ]
380 380 * o.getAllResponseHeaders
381 381 * o.responseText
382 382 * o.responseXML
383 383 * o.argument
384 384 * @param f_call: failure callback
385 385 * @param args arguments
386 386 */
387 387 function ypjax(url,container,s_call,f_call,args){
388 388 var method='GET';
389 389 if(args===undefined){
390 390 args=null;
391 391 }
392 392
393 393 // Set special header for partial ajax == HTTP_X_PARTIAL_XHR
394 394 YUC.initHeader('X-PARTIAL-XHR',true);
395 395
396 396 // wrapper of passed callback
397 397 var s_wrapper = (function(o){
398 398 return function(o){
399 399 YUD.get(container).innerHTML=o.responseText;
400 400 YUD.setStyle(container,'opacity','1.0');
401 401 //execute the given original callback
402 402 if (s_call !== undefined){
403 403 s_call(o);
404 404 }
405 405 }
406 406 })()
407 407 YUD.setStyle(container,'opacity','0.3');
408 408 YUC.asyncRequest(method,url,{
409 409 success:s_wrapper,
410 410 failure:function(o){
411 411 console.log(o);
412 412 YUD.get(container).innerHTML='<span class="error_red">ERROR: {0}</span>'.format(o.status);
413 413 YUD.setStyle(container,'opacity','1.0');
414 414 },
415 415 cache:false
416 416 },args);
417 417
418 418 };
419 419
420 420 var ajaxGET = function(url,success) {
421 421 // Set special header for ajax == HTTP_X_PARTIAL_XHR
422 422 YUC.initHeader('X-PARTIAL-XHR',true);
423 423
424 424 var sUrl = url;
425 425 var callback = {
426 426 success: success,
427 427 failure: function (o) {
428 428 if (o.status != 0) {
429 429 alert("error: " + o.statusText);
430 430 };
431 431 },
432 432 };
433 433
434 434 var request = YAHOO.util.Connect.asyncRequest('GET', sUrl, callback);
435 435 return request;
436 436 };
437 437
438 438
439 439
440 440 var ajaxPOST = function(url,postData,success) {
441 441 // Set special header for ajax == HTTP_X_PARTIAL_XHR
442 442 YUC.initHeader('X-PARTIAL-XHR',true);
443 443
444 444 var toQueryString = function(o) {
445 445 if(typeof o !== 'object') {
446 446 return false;
447 447 }
448 448 var _p, _qs = [];
449 449 for(_p in o) {
450 450 _qs.push(encodeURIComponent(_p) + '=' + encodeURIComponent(o[_p]));
451 451 }
452 452 return _qs.join('&');
453 453 };
454 454
455 455 var sUrl = url;
456 456 var callback = {
457 457 success: success,
458 458 failure: function (o) {
459 459 alert("error");
460 460 },
461 461 };
462 462 var postData = toQueryString(postData);
463 463 var request = YAHOO.util.Connect.asyncRequest('POST', sUrl, callback, postData);
464 464 return request;
465 465 };
466 466
467 467
468 468 /**
469 469 * tooltip activate
470 470 */
471 471 var tooltip_activate = function(){
472 472 yt = YAHOO.yuitip.main;
473 473 YUE.onDOMReady(yt.init);
474 474 };
475 475
476 476 /**
477 477 * show more
478 478 */
479 479 var show_more_event = function(){
480 480 YUE.on(YUD.getElementsByClassName('show_more'),'click',function(e){
481 481 var el = e.target;
482 482 YUD.setStyle(YUD.get(el.id.substring(1)),'display','');
483 483 YUD.setStyle(el.parentNode,'display','none');
484 484 });
485 485 };
486 486
487 487 /**
488 488 * show changeset tooltip
489 489 */
490 490 var show_changeset_tooltip = function(){
491 491 YUE.on(YUD.getElementsByClassName('lazy-cs'), 'mouseover', function(e){
492 492 var target = e.currentTarget;
493 493 var rid = YUD.getAttribute(target,'raw_id');
494 494 var repo_name = YUD.getAttribute(target,'repo_name');
495 495 var ttid = 'tt-'+rid;
496 496 var success = function(o){
497 497 var json = JSON.parse(o.responseText);
498 498 YUD.addClass(target,'tooltip')
499 499 YUD.setAttribute(target, 'title',json['message']);
500 500 YAHOO.yuitip.main.show_yuitip(e, target);
501 501 }
502 502 if(rid && !YUD.hasClass(target, 'tooltip')){
503 503 YUD.setAttribute(target,'id',ttid);
504 504 YUD.setAttribute(target, 'title',_TM['loading...']);
505 505 YAHOO.yuitip.main.set_listeners(target);
506 506 YAHOO.yuitip.main.show_yuitip(e, target);
507 507 var url = pyroutes.url('changeset_info', {"repo_name":repo_name, "revision": rid});
508 508 ajaxGET(url, success)
509 509 }
510 510 });
511 511 };
512 512
513 513 var onSuccessFollow = function(target){
514 514 var f = YUD.get(target);
515 515 var f_cnt = YUD.get('current_followers_count');
516 516
517 517 if(YUD.hasClass(f, 'follow')){
518 518 f.setAttribute('class','following');
519 519 f.setAttribute('title',_TM['Stop following this repository']);
520 520
521 521 if(f_cnt){
522 522 var cnt = Number(f_cnt.innerHTML)+1;
523 523 f_cnt.innerHTML = cnt;
524 524 }
525 525 }
526 526 else{
527 527 f.setAttribute('class','follow');
528 528 f.setAttribute('title',_TM['Start following this repository']);
529 529 if(f_cnt){
530 530 var cnt = Number(f_cnt.innerHTML)-1;
531 531 f_cnt.innerHTML = cnt;
532 532 }
533 533 }
534 534 }
535 535
536 536 var toggleFollowingUser = function(target,fallows_user_id,token,user_id){
537 537 args = 'follows_user_id='+fallows_user_id;
538 538 args+= '&amp;auth_token='+token;
539 539 if(user_id != undefined){
540 540 args+="&amp;user_id="+user_id;
541 541 }
542 542 YUC.asyncRequest('POST',TOGGLE_FOLLOW_URL,{
543 543 success:function(o){
544 544 onSuccessFollow(target);
545 545 }
546 546 },args);
547 547 return false;
548 548 }
549 549
550 550 var toggleFollowingRepo = function(target,fallows_repo_id,token,user_id){
551 551
552 552 args = 'follows_repo_id='+fallows_repo_id;
553 553 args+= '&amp;auth_token='+token;
554 554 if(user_id != undefined){
555 555 args+="&amp;user_id="+user_id;
556 556 }
557 557 YUC.asyncRequest('POST',TOGGLE_FOLLOW_URL,{
558 558 success:function(o){
559 559 onSuccessFollow(target);
560 560 }
561 561 },args);
562 562 return false;
563 563 }
564 564
565 565 var showRepoSize = function(target, repo_name, token){
566 566 var args= 'auth_token='+token;
567 567
568 568 if(!YUD.hasClass(target, 'loaded')){
569 569 YUD.get(target).innerHTML = _TM['Loading ...'];
570 570 var url = pyroutes.url('repo_size', {"repo_name":repo_name});
571 571 YUC.asyncRequest('POST',url,{
572 572 success:function(o){
573 573 YUD.get(target).innerHTML = JSON.parse(o.responseText);
574 574 YUD.addClass(target, 'loaded');
575 575 }
576 576 },args);
577 577 }
578 578 return false;
579 579 }
580 580
581 581 /**
582 582 * TOOLTIP IMPL.
583 583 */
584 584 YAHOO.namespace('yuitip');
585 585 YAHOO.yuitip.main = {
586 586
587 587 $: YAHOO.util.Dom.get,
588 588
589 589 bgColor: '#000',
590 590 speed: 0.3,
591 591 opacity: 0.9,
592 592 offset: [15,15],
593 593 useAnim: false,
594 594 maxWidth: 600,
595 595 add_links: false,
596 596 yuitips: [],
597 597
598 598 set_listeners: function(tt){
599 599 YUE.on(tt, 'mouseover', yt.show_yuitip, tt);
600 600 YUE.on(tt, 'mousemove', yt.move_yuitip, tt);
601 601 YUE.on(tt, 'mouseout', yt.close_yuitip, tt);
602 602 },
603 603
604 604 init: function(){
605 605 yt.tipBox = yt.$('tip-box');
606 606 if(!yt.tipBox){
607 607 yt.tipBox = document.createElement('div');
608 608 document.body.appendChild(yt.tipBox);
609 609 yt.tipBox.id = 'tip-box';
610 610 }
611 611
612 612 YUD.setStyle(yt.tipBox, 'display', 'none');
613 613 YUD.setStyle(yt.tipBox, 'position', 'absolute');
614 614 if(yt.maxWidth !== null){
615 615 YUD.setStyle(yt.tipBox, 'max-width', yt.maxWidth+'px');
616 616 }
617 617
618 618 var yuitips = YUD.getElementsByClassName('tooltip');
619 619
620 620 if(yt.add_links === true){
621 621 var links = document.getElementsByTagName('a');
622 622 var linkLen = links.length;
623 623 for(i=0;i<linkLen;i++){
624 624 yuitips.push(links[i]);
625 625 }
626 626 }
627 627
628 628 var yuiLen = yuitips.length;
629 629
630 630 for(i=0;i<yuiLen;i++){
631 631 yt.set_listeners(yuitips[i]);
632 632 }
633 633 },
634 634
635 635 show_yuitip: function(e, el){
636 636 YUE.stopEvent(e);
637 637 if(el.tagName.toLowerCase() === 'img'){
638 638 yt.tipText = el.alt ? el.alt : '';
639 639 } else {
640 640 yt.tipText = el.title ? el.title : '';
641 641 }
642 642
643 643 if(yt.tipText !== ''){
644 644 // save org title
645 645 YUD.setAttribute(el, 'tt_title', yt.tipText);
646 646 // reset title to not show org tooltips
647 647 YUD.setAttribute(el, 'title', '');
648 648
649 649 yt.tipBox.innerHTML = yt.tipText;
650 650 YUD.setStyle(yt.tipBox, 'display', 'block');
651 651 if(yt.useAnim === true){
652 652 YUD.setStyle(yt.tipBox, 'opacity', '0');
653 653 var newAnim = new YAHOO.util.Anim(yt.tipBox,
654 654 {
655 655 opacity: { to: yt.opacity }
656 656 }, yt.speed, YAHOO.util.Easing.easeOut
657 657 );
658 658 newAnim.animate();
659 659 }
660 660 }
661 661 },
662 662
663 663 move_yuitip: function(e, el){
664 664 YUE.stopEvent(e);
665 665 var movePos = YUE.getXY(e);
666 666 YUD.setStyle(yt.tipBox, 'top', (movePos[1] + yt.offset[1]) + 'px');
667 667 YUD.setStyle(yt.tipBox, 'left', (movePos[0] + yt.offset[0]) + 'px');
668 668 },
669 669
670 670 close_yuitip: function(e, el){
671 671 YUE.stopEvent(e);
672 672
673 673 if(yt.useAnim === true){
674 674 var newAnim = new YAHOO.util.Anim(yt.tipBox,
675 675 {
676 676 opacity: { to: 0 }
677 677 }, yt.speed, YAHOO.util.Easing.easeOut
678 678 );
679 679 newAnim.animate();
680 680 } else {
681 681 YUD.setStyle(yt.tipBox, 'display', 'none');
682 682 }
683 683 YUD.setAttribute(el,'title', YUD.getAttribute(el, 'tt_title'));
684 684 }
685 685 }
686 686
687 687 /**
688 688 * Quick filter widget
689 689 *
690 690 * @param target: filter input target
691 691 * @param nodes: list of nodes in html we want to filter.
692 692 * @param display_element function that takes current node from nodes and
693 693 * does hide or show based on the node
694 694 *
695 695 */
696 696 var q_filter = function(target,nodes,display_element){
697 697
698 698 var nodes = nodes;
699 699 var q_filter_field = YUD.get(target);
700 700 var F = YAHOO.namespace(target);
701 701
702 YUE.on(q_filter_field,'click',function(){
703 q_filter_field.value = '';
704 });
705
706 702 YUE.on(q_filter_field,'keyup',function(e){
707 703 clearTimeout(F.filterTimeout);
708 704 F.filterTimeout = setTimeout(F.updateFilter,600);
709 705 });
710 706
711 707 F.filterTimeout = null;
712 708
713 709 var show_node = function(node){
714 710 YUD.setStyle(node,'display','')
715 711 }
716 712 var hide_node = function(node){
717 713 YUD.setStyle(node,'display','none');
718 714 }
719 715
720 716 F.updateFilter = function() {
721 717 // Reset timeout
722 718 F.filterTimeout = null;
723 719
724 720 var obsolete = [];
725 721
726 722 var req = q_filter_field.value.toLowerCase();
727 723
728 724 var l = nodes.length;
729 725 var i;
730 726 var showing = 0;
731 727
732 728 for (i=0;i<l;i++ ){
733 729 var n = nodes[i];
734 730 var target_element = display_element(n)
735 731 if(req && n.innerHTML.toLowerCase().indexOf(req) == -1){
736 732 hide_node(target_element);
737 733 }
738 734 else{
739 735 show_node(target_element);
740 736 showing+=1;
741 737 }
742 738 }
743 739
744 740 // if repo_count is set update the number
745 741 var cnt = YUD.get('repo_count');
746 742 if(cnt){
747 743 YUD.get('repo_count').innerHTML = showing;
748 744 }
749 745
750 746 }
751 747 };
752 748
753 749 var tableTr = function(cls, body){
754 750 var _el = document.createElement('div');
755 751 var cont = new YAHOO.util.Element(body);
756 752 var comment_id = fromHTML(body).children[0].id.split('comment-')[1];
757 753 var id = 'comment-tr-{0}'.format(comment_id);
758 754 var _html = ('<table><tbody><tr id="{0}" class="{1}">'+
759 755 '<td class="lineno-inline new-inline"></td>'+
760 756 '<td class="lineno-inline old-inline"></td>'+
761 757 '<td>{2}</td>'+
762 758 '</tr></tbody></table>').format(id, cls, body);
763 759 _el.innerHTML = _html;
764 760 return _el.children[0].children[0].children[0];
765 761 };
766 762
767 763 /** comments **/
768 764 var removeInlineForm = function(form) {
769 765 form.parentNode.removeChild(form);
770 766 };
771 767
772 768 var createInlineForm = function(parent_tr, f_path, line) {
773 769 var tmpl = YUD.get('comment-inline-form-template').innerHTML;
774 770 tmpl = tmpl.format(f_path, line);
775 771 var form = tableTr('comment-form-inline',tmpl)
776 772
777 773 // create event for hide button
778 774 form = new YAHOO.util.Element(form);
779 775 var form_hide_button = new YAHOO.util.Element(YUD.getElementsByClassName('hide-inline-form',null,form)[0]);
780 776 form_hide_button.on('click', function(e) {
781 777 var newtr = e.currentTarget.parentNode.parentNode.parentNode.parentNode.parentNode;
782 778 if(YUD.hasClass(newtr.nextElementSibling,'inline-comments-button')){
783 779 YUD.setStyle(newtr.nextElementSibling,'display','');
784 780 }
785 781 removeInlineForm(newtr);
786 782 YUD.removeClass(parent_tr, 'form-open');
787 783 YUD.removeClass(parent_tr, 'hl-comment');
788 784
789 785 });
790 786
791 787 return form
792 788 };
793 789
794 790 /**
795 791 * Inject inline comment for on given TR this tr should be always an .line
796 792 * tr containing the line. Code will detect comment, and always put the comment
797 793 * block at the very bottom
798 794 */
799 795 var injectInlineForm = function(tr){
800 796 if(!YUD.hasClass(tr, 'line')){
801 797 return
802 798 }
803 799 var submit_url = AJAX_COMMENT_URL;
804 800 var _td = YUD.getElementsByClassName('code',null,tr)[0];
805 801 if(YUD.hasClass(tr,'form-open') || YUD.hasClass(tr,'context') || YUD.hasClass(_td,'no-comment')){
806 802 return
807 803 }
808 804 YUD.addClass(tr,'form-open');
809 805 YUD.addClass(tr,'hl-comment');
810 806 var node = YUD.getElementsByClassName('full_f_path',null,tr.parentNode.parentNode.parentNode)[0];
811 807 var f_path = YUD.getAttribute(node,'path');
812 808 var lineno = getLineNo(tr);
813 809 var form = createInlineForm(tr, f_path, lineno, submit_url);
814 810
815 811 var parent = tr;
816 812 while (1){
817 813 var n = parent.nextElementSibling;
818 814 // next element are comments !
819 815 if(YUD.hasClass(n,'inline-comments')){
820 816 parent = n;
821 817 }
822 818 else{
823 819 break;
824 820 }
825 821 }
826 822 YUD.insertAfter(form,parent);
827 823 var f = YUD.get(form);
828 824 var overlay = YUD.getElementsByClassName('overlay',null,f)[0];
829 825 var _form = YUD.getElementsByClassName('inline-form',null,f)[0];
830 826
831 827 YUE.on(YUD.get(_form), 'submit',function(e){
832 828 YUE.preventDefault(e);
833 829
834 830 //ajax submit
835 831 var text = YUD.get('text_'+lineno).value;
836 832 var postData = {
837 833 'text':text,
838 834 'f_path':f_path,
839 835 'line':lineno
840 836 };
841 837
842 838 if(lineno === undefined){
843 839 alert('missing line !');
844 840 return
845 841 }
846 842 if(f_path === undefined){
847 843 alert('missing file path !');
848 844 return
849 845 }
850 846
851 847 if(text == ""){
852 848 return
853 849 }
854 850
855 851 var success = function(o){
856 852 YUD.removeClass(tr, 'form-open');
857 853 removeInlineForm(f);
858 854 var json_data = JSON.parse(o.responseText);
859 855 renderInlineComment(json_data);
860 856 };
861 857
862 858 if (YUD.hasClass(overlay,'overlay')){
863 859 var w = _form.offsetWidth;
864 860 var h = _form.offsetHeight;
865 861 YUD.setStyle(overlay,'width',w+'px');
866 862 YUD.setStyle(overlay,'height',h+'px');
867 863 }
868 864 YUD.addClass(overlay, 'submitting');
869 865
870 866 ajaxPOST(submit_url, postData, success);
871 867 });
872 868
873 869 setTimeout(function(){
874 870 // callbacks
875 871 tooltip_activate();
876 872 MentionsAutoComplete('text_'+lineno, 'mentions_container_'+lineno,
877 873 _USERS_AC_DATA, _GROUPS_AC_DATA);
878 874 var _e = YUD.get('text_'+lineno);
879 875 if(_e){
880 876 _e.focus();
881 877 }
882 878 },10)
883 879 };
884 880
885 881 var deleteComment = function(comment_id){
886 882 var url = AJAX_COMMENT_DELETE_URL.replace('__COMMENT_ID__',comment_id);
887 883 var postData = {'_method':'delete'};
888 884 var success = function(o){
889 885 var n = YUD.get('comment-tr-'+comment_id);
890 886 var root = prevElementSibling(prevElementSibling(n));
891 887 n.parentNode.removeChild(n);
892 888
893 889 // scann nodes, and attach add button to last one
894 890 placeAddButton(root);
895 891 }
896 892 ajaxPOST(url,postData,success);
897 893 }
898 894
899 895 var createInlineAddButton = function(tr){
900 896
901 897 var label = TRANSLATION_MAP['Add another comment'];
902 898
903 899 var html_el = document.createElement('div');
904 900 YUD.addClass(html_el, 'add-comment');
905 901 html_el.innerHTML = '<span class="ui-btn">{0}</span>'.format(label);
906 902
907 903 var add = new YAHOO.util.Element(html_el);
908 904 add.on('click', function(e) {
909 905 injectInlineForm(tr);
910 906 });
911 907 return add;
912 908 };
913 909
914 910 var getLineNo = function(tr) {
915 911 var line;
916 912 var o = tr.children[0].id.split('_');
917 913 var n = tr.children[1].id.split('_');
918 914
919 915 if (n.length >= 2) {
920 916 line = n[n.length-1];
921 917 } else if (o.length >= 2) {
922 918 line = o[o.length-1];
923 919 }
924 920
925 921 return line
926 922 };
927 923
928 924 var placeAddButton = function(target_tr){
929 925 if(!target_tr){
930 926 return
931 927 }
932 928 var last_node = target_tr;
933 929 //scann
934 930 while (1){
935 931 var n = last_node.nextElementSibling;
936 932 // next element are comments !
937 933 if(YUD.hasClass(n,'inline-comments')){
938 934 last_node = n;
939 935 //also remove the comment button from previous
940 936 var comment_add_buttons = YUD.getElementsByClassName('add-comment',null,last_node);
941 937 for(var i=0;i<comment_add_buttons.length;i++){
942 938 var b = comment_add_buttons[i];
943 939 b.parentNode.removeChild(b);
944 940 }
945 941 }
946 942 else{
947 943 break;
948 944 }
949 945 }
950 946
951 947 var add = createInlineAddButton(target_tr);
952 948 // get the comment div
953 949 var comment_block = YUD.getElementsByClassName('comment',null,last_node)[0];
954 950 // attach add button
955 951 YUD.insertAfter(add,comment_block);
956 952 }
957 953
958 954 /**
959 955 * Places the inline comment into the changeset block in proper line position
960 956 */
961 957 var placeInline = function(target_container,lineno,html){
962 958 var lineid = "{0}_{1}".format(target_container,lineno);
963 959 var target_line = YUD.get(lineid);
964 960 var comment = new YAHOO.util.Element(tableTr('inline-comments',html))
965 961
966 962 // check if there are comments already !
967 963 var parent = target_line.parentNode;
968 964 var root_parent = parent;
969 965 while (1){
970 966 var n = parent.nextElementSibling;
971 967 // next element are comments !
972 968 if(YUD.hasClass(n,'inline-comments')){
973 969 parent = n;
974 970 }
975 971 else{
976 972 break;
977 973 }
978 974 }
979 975 // put in the comment at the bottom
980 976 YUD.insertAfter(comment,parent);
981 977
982 978 // scann nodes, and attach add button to last one
983 979 placeAddButton(root_parent);
984 980
985 981 return target_line;
986 982 }
987 983
988 984 /**
989 985 * make a single inline comment and place it inside
990 986 */
991 987 var renderInlineComment = function(json_data){
992 988 try{
993 989 var html = json_data['rendered_text'];
994 990 var lineno = json_data['line_no'];
995 991 var target_id = json_data['target_id'];
996 992 placeInline(target_id, lineno, html);
997 993
998 994 }catch(e){
999 995 console.log(e);
1000 996 }
1001 997 }
1002 998
1003 999 /**
1004 1000 * Iterates over all the inlines, and places them inside proper blocks of data
1005 1001 */
1006 1002 var renderInlineComments = function(file_comments){
1007 1003 for (f in file_comments){
1008 1004 // holding all comments for a FILE
1009 1005 var box = file_comments[f];
1010 1006
1011 1007 var target_id = YUD.getAttribute(box,'target_id');
1012 1008 // actually comments with line numbers
1013 1009 var comments = box.children;
1014 1010 for(var i=0; i<comments.length; i++){
1015 1011 var data = {
1016 1012 'rendered_text': comments[i].outerHTML,
1017 1013 'line_no': YUD.getAttribute(comments[i],'line'),
1018 1014 'target_id': target_id
1019 1015 }
1020 1016 renderInlineComment(data);
1021 1017 }
1022 1018 }
1023 1019 }
1024 1020
1025 1021 var fileBrowserListeners = function(current_url, node_list_url, url_base){
1026 1022 var current_url_branch = +"?branch=__BRANCH__";
1027 1023
1028 1024 YUE.on('stay_at_branch','click',function(e){
1029 1025 if(e.target.checked){
1030 1026 var uri = current_url_branch;
1031 1027 uri = uri.replace('__BRANCH__',e.target.value);
1032 1028 window.location = uri;
1033 1029 }
1034 1030 else{
1035 1031 window.location = current_url;
1036 1032 }
1037 1033 })
1038 1034
1039 1035 var n_filter = YUD.get('node_filter');
1040 1036 var F = YAHOO.namespace('node_filter');
1041 1037
1042 1038 F.filterTimeout = null;
1043 1039 var nodes = null;
1044 1040
1045 1041 F.initFilter = function(){
1046 1042 YUD.setStyle('node_filter_box_loading','display','');
1047 1043 YUD.setStyle('search_activate_id','display','none');
1048 1044 YUD.setStyle('add_node_id','display','none');
1049 1045 YUC.initHeader('X-PARTIAL-XHR',true);
1050 1046 YUC.asyncRequest('GET', node_list_url, {
1051 1047 success:function(o){
1052 1048 nodes = JSON.parse(o.responseText).nodes;
1053 1049 YUD.setStyle('node_filter_box_loading','display','none');
1054 1050 YUD.setStyle('node_filter_box','display','');
1055 1051 n_filter.focus();
1056 1052 if(YUD.hasClass(n_filter,'init')){
1057 1053 n_filter.value = '';
1058 1054 YUD.removeClass(n_filter,'init');
1059 1055 }
1060 1056 },
1061 1057 failure:function(o){
1062 1058 console.log('failed to load');
1063 1059 }
1064 1060 },null);
1065 1061 }
1066 1062
1067 1063 F.updateFilter = function(e) {
1068 1064
1069 1065 return function(){
1070 1066 // Reset timeout
1071 1067 F.filterTimeout = null;
1072 1068 var query = e.target.value.toLowerCase();
1073 1069 var match = [];
1074 1070 var matches = 0;
1075 1071 var matches_max = 20;
1076 1072 if (query != ""){
1077 1073 for(var i=0;i<nodes.length;i++){
1078 1074
1079 1075 var pos = nodes[i].name.toLowerCase().indexOf(query)
1080 1076 if(query && pos != -1){
1081 1077
1082 1078 matches++
1083 1079 //show only certain amount to not kill browser
1084 1080 if (matches > matches_max){
1085 1081 break;
1086 1082 }
1087 1083
1088 1084 var n = nodes[i].name;
1089 1085 var t = nodes[i].type;
1090 1086 var n_hl = n.substring(0,pos)
1091 1087 +"<b>{0}</b>".format(n.substring(pos,pos+query.length))
1092 1088 +n.substring(pos+query.length)
1093 1089 var new_url = url_base.replace('__FPATH__',n);
1094 1090 match.push('<tr><td><a class="browser-{0}" href="{1}">{2}</a></td><td colspan="5"></td></tr>'.format(t,new_url,n_hl));
1095 1091 }
1096 1092 if(match.length >= matches_max){
1097 1093 match.push('<tr><td>{0}</td><td colspan="5"></td></tr>'.format(_TM['Search truncated']));
1098 1094 }
1099 1095 }
1100 1096 }
1101 1097 if(query != ""){
1102 1098 YUD.setStyle('tbody','display','none');
1103 1099 YUD.setStyle('tbody_filtered','display','');
1104 1100
1105 1101 if (match.length==0){
1106 1102 match.push('<tr><td>{0}</td><td colspan="5"></td></tr>'.format(_TM['No matching files']));
1107 1103 }
1108 1104
1109 1105 YUD.get('tbody_filtered').innerHTML = match.join("");
1110 1106 }
1111 1107 else{
1112 1108 YUD.setStyle('tbody','display','');
1113 1109 YUD.setStyle('tbody_filtered','display','none');
1114 1110 }
1115 1111
1116 1112 }
1117 1113 };
1118 1114
1119 1115 YUE.on(YUD.get('filter_activate'),'click',function(){
1120 1116 F.initFilter();
1121 1117 })
1122 1118 YUE.on(n_filter,'click',function(){
1123 1119 if(YUD.hasClass(n_filter,'init')){
1124 1120 n_filter.value = '';
1125 1121 YUD.removeClass(n_filter,'init');
1126 1122 }
1127 1123 });
1128 1124 YUE.on(n_filter,'keyup',function(e){
1129 1125 clearTimeout(F.filterTimeout);
1130 1126 F.filterTimeout = setTimeout(F.updateFilter(e),600);
1131 1127 });
1132 1128 };
1133 1129
1134 1130
1135 1131 var initCodeMirror = function(textAreadId,resetUrl){
1136 1132 var myCodeMirror = CodeMirror.fromTextArea(YUD.get(textAreadId),{
1137 1133 mode: "null",
1138 1134 lineNumbers:true
1139 1135 });
1140 1136 YUE.on('reset','click',function(e){
1141 1137 window.location=resetUrl
1142 1138 });
1143 1139
1144 1140 YUE.on('file_enable','click',function(){
1145 1141 YUD.setStyle('editor_container','display','');
1146 1142 YUD.setStyle('upload_file_container','display','none');
1147 1143 YUD.setStyle('filename_container','display','');
1148 1144 });
1149 1145
1150 1146 YUE.on('upload_file_enable','click',function(){
1151 1147 YUD.setStyle('editor_container','display','none');
1152 1148 YUD.setStyle('upload_file_container','display','');
1153 1149 YUD.setStyle('filename_container','display','none');
1154 1150 });
1155 1151 };
1156 1152
1157 1153
1158 1154
1159 1155 var getIdentNode = function(n){
1160 1156 //iterate thru nodes untill matched interesting node !
1161 1157
1162 1158 if (typeof n == 'undefined'){
1163 1159 return -1
1164 1160 }
1165 1161
1166 1162 if(typeof n.id != "undefined" && n.id.match('L[0-9]+')){
1167 1163 return n
1168 1164 }
1169 1165 else{
1170 1166 return getIdentNode(n.parentNode);
1171 1167 }
1172 1168 };
1173 1169
1174 1170 var getSelectionLink = function(e) {
1175 1171
1176 1172 //get selection from start/to nodes
1177 1173 if (typeof window.getSelection != "undefined") {
1178 1174 s = window.getSelection();
1179 1175
1180 1176 from = getIdentNode(s.anchorNode);
1181 1177 till = getIdentNode(s.focusNode);
1182 1178
1183 1179 f_int = parseInt(from.id.replace('L',''));
1184 1180 t_int = parseInt(till.id.replace('L',''));
1185 1181
1186 1182 if (f_int > t_int){
1187 1183 //highlight from bottom
1188 1184 offset = -35;
1189 1185 ranges = [t_int,f_int];
1190 1186
1191 1187 }
1192 1188 else{
1193 1189 //highligth from top
1194 1190 offset = 35;
1195 1191 ranges = [f_int,t_int];
1196 1192 }
1197 1193 // if we select more than 2 lines
1198 1194 if (ranges[0] != ranges[1]){
1199 1195 if(YUD.get('linktt') == null){
1200 1196 hl_div = document.createElement('div');
1201 1197 hl_div.id = 'linktt';
1202 1198 }
1203 1199 hl_div.innerHTML = '';
1204 1200
1205 1201 anchor = '#L'+ranges[0]+'-'+ranges[1];
1206 1202 var link = document.createElement('a');
1207 1203 link.href = location.href.substring(0,location.href.indexOf('#'))+anchor;
1208 1204 link.innerHTML = _TM['Selection link'];
1209 1205 hl_div.appendChild(link);
1210 1206 YUD.get('body').appendChild(hl_div);
1211 1207
1212 1208 xy = YUD.getXY(till.id);
1213 1209
1214 1210 YUD.addClass('linktt', 'hl-tip-box');
1215 1211 YUD.setStyle('linktt','top',xy[1]+offset+'px');
1216 1212 YUD.setStyle('linktt','left',xy[0]+'px');
1217 1213 YUD.setStyle('linktt','visibility','visible');
1218 1214
1219 1215 }
1220 1216 else{
1221 1217 YUD.setStyle('linktt','visibility','hidden');
1222 1218 }
1223 1219 }
1224 1220 };
1225 1221
1226 1222 var deleteNotification = function(url, notification_id,callbacks){
1227 1223 var callback = {
1228 1224 success:function(o){
1229 1225 var obj = YUD.get(String("notification_"+notification_id));
1230 1226 if(obj.parentNode !== undefined){
1231 1227 obj.parentNode.removeChild(obj);
1232 1228 }
1233 1229 _run_callbacks(callbacks);
1234 1230 },
1235 1231 failure:function(o){
1236 1232 alert("error");
1237 1233 },
1238 1234 };
1239 1235 var postData = '_method=delete';
1240 1236 var sUrl = url.replace('__NOTIFICATION_ID__',notification_id);
1241 1237 var request = YAHOO.util.Connect.asyncRequest('POST', sUrl,
1242 1238 callback, postData);
1243 1239 };
1244 1240
1245 1241 var readNotification = function(url, notification_id,callbacks){
1246 1242 var callback = {
1247 1243 success:function(o){
1248 1244 var obj = YUD.get(String("notification_"+notification_id));
1249 1245 YUD.removeClass(obj, 'unread');
1250 1246 var r_button = YUD.getElementsByClassName('read-notification',null,obj.children[0])[0];
1251 1247
1252 1248 if(r_button.parentNode !== undefined){
1253 1249 r_button.parentNode.removeChild(r_button);
1254 1250 }
1255 1251 _run_callbacks(callbacks);
1256 1252 },
1257 1253 failure:function(o){
1258 1254 alert("error");
1259 1255 },
1260 1256 };
1261 1257 var postData = '_method=put';
1262 1258 var sUrl = url.replace('__NOTIFICATION_ID__',notification_id);
1263 1259 var request = YAHOO.util.Connect.asyncRequest('POST', sUrl,
1264 1260 callback, postData);
1265 1261 };
1266 1262
1267 1263 /** MEMBERS AUTOCOMPLETE WIDGET **/
1268 1264
1269 1265 var MembersAutoComplete = function (divid, cont, users_list, groups_list) {
1270 1266 var myUsers = users_list;
1271 1267 var myGroups = groups_list;
1272 1268
1273 1269 // Define a custom search function for the DataSource of users
1274 1270 var matchUsers = function (sQuery) {
1275 1271 // Case insensitive matching
1276 1272 var query = sQuery.toLowerCase();
1277 1273 var i = 0;
1278 1274 var l = myUsers.length;
1279 1275 var matches = [];
1280 1276
1281 1277 // Match against each name of each contact
1282 1278 for (; i < l; i++) {
1283 1279 contact = myUsers[i];
1284 1280 if (((contact.fname+"").toLowerCase().indexOf(query) > -1) ||
1285 1281 ((contact.lname+"").toLowerCase().indexOf(query) > -1) ||
1286 1282 ((contact.nname) && ((contact.nname).toLowerCase().indexOf(query) > -1))) {
1287 1283 matches[matches.length] = contact;
1288 1284 }
1289 1285 }
1290 1286 return matches;
1291 1287 };
1292 1288
1293 1289 // Define a custom search function for the DataSource of userGroups
1294 1290 var matchGroups = function (sQuery) {
1295 1291 // Case insensitive matching
1296 1292 var query = sQuery.toLowerCase();
1297 1293 var i = 0;
1298 1294 var l = myGroups.length;
1299 1295 var matches = [];
1300 1296
1301 1297 // Match against each name of each contact
1302 1298 for (; i < l; i++) {
1303 1299 matched_group = myGroups[i];
1304 1300 if (matched_group.grname.toLowerCase().indexOf(query) > -1) {
1305 1301 matches[matches.length] = matched_group;
1306 1302 }
1307 1303 }
1308 1304 return matches;
1309 1305 };
1310 1306
1311 1307 //match all
1312 1308 var matchAll = function (sQuery) {
1313 1309 u = matchUsers(sQuery);
1314 1310 g = matchGroups(sQuery);
1315 1311 return u.concat(g);
1316 1312 };
1317 1313
1318 1314 // DataScheme for members
1319 1315 var memberDS = new YAHOO.util.FunctionDataSource(matchAll);
1320 1316 memberDS.responseSchema = {
1321 1317 fields: ["id", "fname", "lname", "nname", "grname", "grmembers", "gravatar_lnk"]
1322 1318 };
1323 1319
1324 1320 // DataScheme for owner
1325 1321 var ownerDS = new YAHOO.util.FunctionDataSource(matchUsers);
1326 1322 ownerDS.responseSchema = {
1327 1323 fields: ["id", "fname", "lname", "nname", "gravatar_lnk"]
1328 1324 };
1329 1325
1330 1326 // Instantiate AutoComplete for perms
1331 1327 var membersAC = new YAHOO.widget.AutoComplete(divid, cont, memberDS);
1332 1328 membersAC.useShadow = false;
1333 1329 membersAC.resultTypeList = false;
1334 1330 membersAC.animVert = false;
1335 1331 membersAC.animHoriz = false;
1336 1332 membersAC.animSpeed = 0.1;
1337 1333
1338 1334 // Instantiate AutoComplete for owner
1339 1335 var ownerAC = new YAHOO.widget.AutoComplete("user", "owner_container", ownerDS);
1340 1336 ownerAC.useShadow = false;
1341 1337 ownerAC.resultTypeList = false;
1342 1338 ownerAC.animVert = false;
1343 1339 ownerAC.animHoriz = false;
1344 1340 ownerAC.animSpeed = 0.1;
1345 1341
1346 1342 // Helper highlight function for the formatter
1347 1343 var highlightMatch = function (full, snippet, matchindex) {
1348 1344 return full.substring(0, matchindex)
1349 1345 + "<span class='match'>"
1350 1346 + full.substr(matchindex, snippet.length)
1351 1347 + "</span>" + full.substring(matchindex + snippet.length);
1352 1348 };
1353 1349
1354 1350 // Custom formatter to highlight the matching letters
1355 1351 var custom_formatter = function (oResultData, sQuery, sResultMatch) {
1356 1352 var query = sQuery.toLowerCase();
1357 1353 var _gravatar = function(res, em, group){
1358 1354 if (group !== undefined){
1359 1355 em = '/images/icons/group.png'
1360 1356 }
1361 1357 tmpl = '<div class="ac-container-wrap"><img class="perm-gravatar-ac" src="{0}"/>{1}</div>'
1362 1358 return tmpl.format(em,res)
1363 1359 }
1364 1360 // group
1365 1361 if (oResultData.grname != undefined) {
1366 1362 var grname = oResultData.grname;
1367 1363 var grmembers = oResultData.grmembers;
1368 1364 var grnameMatchIndex = grname.toLowerCase().indexOf(query);
1369 1365 var grprefix = "{0}: ".format(_TM['Group']);
1370 1366 var grsuffix = " (" + grmembers + " )";
1371 1367 var grsuffix = " ({0} {1})".format(grmembers, _TM['members']);
1372 1368
1373 1369 if (grnameMatchIndex > -1) {
1374 1370 return _gravatar(grprefix + highlightMatch(grname, query, grnameMatchIndex) + grsuffix,null,true);
1375 1371 }
1376 1372 return _gravatar(grprefix + oResultData.grname + grsuffix, null,true);
1377 1373 // Users
1378 1374 } else if (oResultData.nname != undefined) {
1379 1375 var fname = oResultData.fname || "";
1380 1376 var lname = oResultData.lname || "";
1381 1377 var nname = oResultData.nname;
1382 1378
1383 1379 // Guard against null value
1384 1380 var fnameMatchIndex = fname.toLowerCase().indexOf(query),
1385 1381 lnameMatchIndex = lname.toLowerCase().indexOf(query),
1386 1382 nnameMatchIndex = nname.toLowerCase().indexOf(query),
1387 1383 displayfname, displaylname, displaynname;
1388 1384
1389 1385 if (fnameMatchIndex > -1) {
1390 1386 displayfname = highlightMatch(fname, query, fnameMatchIndex);
1391 1387 } else {
1392 1388 displayfname = fname;
1393 1389 }
1394 1390
1395 1391 if (lnameMatchIndex > -1) {
1396 1392 displaylname = highlightMatch(lname, query, lnameMatchIndex);
1397 1393 } else {
1398 1394 displaylname = lname;
1399 1395 }
1400 1396
1401 1397 if (nnameMatchIndex > -1) {
1402 1398 displaynname = "(" + highlightMatch(nname, query, nnameMatchIndex) + ")";
1403 1399 } else {
1404 1400 displaynname = nname ? "(" + nname + ")" : "";
1405 1401 }
1406 1402
1407 1403 return _gravatar(displayfname + " " + displaylname + " " + displaynname, oResultData.gravatar_lnk);
1408 1404 } else {
1409 1405 return '';
1410 1406 }
1411 1407 };
1412 1408 membersAC.formatResult = custom_formatter;
1413 1409 ownerAC.formatResult = custom_formatter;
1414 1410
1415 1411 var myHandler = function (sType, aArgs) {
1416 1412 var nextId = divid.split('perm_new_member_name_')[1];
1417 1413 var myAC = aArgs[0]; // reference back to the AC instance
1418 1414 var elLI = aArgs[1]; // reference to the selected LI element
1419 1415 var oData = aArgs[2]; // object literal of selected item's result data
1420 1416 //fill the autocomplete with value
1421 1417 if (oData.nname != undefined) {
1422 1418 //users
1423 1419 myAC.getInputEl().value = oData.nname;
1424 1420 YUD.get('perm_new_member_type_'+nextId).value = 'user';
1425 1421 } else {
1426 1422 //groups
1427 1423 myAC.getInputEl().value = oData.grname;
1428 1424 YUD.get('perm_new_member_type_'+nextId).value = 'users_group';
1429 1425 }
1430 1426 };
1431 1427
1432 1428 membersAC.itemSelectEvent.subscribe(myHandler);
1433 1429 if(ownerAC.itemSelectEvent){
1434 1430 ownerAC.itemSelectEvent.subscribe(myHandler);
1435 1431 }
1436 1432
1437 1433 return {
1438 1434 memberDS: memberDS,
1439 1435 ownerDS: ownerDS,
1440 1436 membersAC: membersAC,
1441 1437 ownerAC: ownerAC,
1442 1438 };
1443 1439 }
1444 1440
1445 1441
1446 1442 var MentionsAutoComplete = function (divid, cont, users_list, groups_list) {
1447 1443 var myUsers = users_list;
1448 1444 var myGroups = groups_list;
1449 1445
1450 1446 // Define a custom search function for the DataSource of users
1451 1447 var matchUsers = function (sQuery) {
1452 1448 var org_sQuery = sQuery;
1453 1449 if(this.mentionQuery == null){
1454 1450 return []
1455 1451 }
1456 1452 sQuery = this.mentionQuery;
1457 1453 // Case insensitive matching
1458 1454 var query = sQuery.toLowerCase();
1459 1455 var i = 0;
1460 1456 var l = myUsers.length;
1461 1457 var matches = [];
1462 1458
1463 1459 // Match against each name of each contact
1464 1460 for (; i < l; i++) {
1465 1461 contact = myUsers[i];
1466 1462 if (((contact.fname+"").toLowerCase().indexOf(query) > -1) ||
1467 1463 ((contact.lname+"").toLowerCase().indexOf(query) > -1) ||
1468 1464 ((contact.nname) && ((contact.nname).toLowerCase().indexOf(query) > -1))) {
1469 1465 matches[matches.length] = contact;
1470 1466 }
1471 1467 }
1472 1468 return matches
1473 1469 };
1474 1470
1475 1471 //match all
1476 1472 var matchAll = function (sQuery) {
1477 1473 u = matchUsers(sQuery);
1478 1474 return u
1479 1475 };
1480 1476
1481 1477 // DataScheme for owner
1482 1478 var ownerDS = new YAHOO.util.FunctionDataSource(matchUsers);
1483 1479
1484 1480 ownerDS.responseSchema = {
1485 1481 fields: ["id", "fname", "lname", "nname", "gravatar_lnk"]
1486 1482 };
1487 1483
1488 1484 // Instantiate AutoComplete for mentions
1489 1485 var ownerAC = new YAHOO.widget.AutoComplete(divid, cont, ownerDS);
1490 1486 ownerAC.useShadow = false;
1491 1487 ownerAC.resultTypeList = false;
1492 1488 ownerAC.suppressInputUpdate = true;
1493 1489 ownerAC.animVert = false;
1494 1490 ownerAC.animHoriz = false;
1495 1491 ownerAC.animSpeed = 0.1;
1496 1492
1497 1493 // Helper highlight function for the formatter
1498 1494 var highlightMatch = function (full, snippet, matchindex) {
1499 1495 return full.substring(0, matchindex)
1500 1496 + "<span class='match'>"
1501 1497 + full.substr(matchindex, snippet.length)
1502 1498 + "</span>" + full.substring(matchindex + snippet.length);
1503 1499 };
1504 1500
1505 1501 // Custom formatter to highlight the matching letters
1506 1502 ownerAC.formatResult = function (oResultData, sQuery, sResultMatch) {
1507 1503 var org_sQuery = sQuery;
1508 1504 if(this.dataSource.mentionQuery != null){
1509 1505 sQuery = this.dataSource.mentionQuery;
1510 1506 }
1511 1507
1512 1508 var query = sQuery.toLowerCase();
1513 1509 var _gravatar = function(res, em, group){
1514 1510 if (group !== undefined){
1515 1511 em = '/images/icons/group.png'
1516 1512 }
1517 1513 tmpl = '<div class="ac-container-wrap"><img class="perm-gravatar-ac" src="{0}"/>{1}</div>'
1518 1514 return tmpl.format(em,res)
1519 1515 }
1520 1516 if (oResultData.nname != undefined) {
1521 1517 var fname = oResultData.fname || "";
1522 1518 var lname = oResultData.lname || "";
1523 1519 var nname = oResultData.nname;
1524 1520
1525 1521 // Guard against null value
1526 1522 var fnameMatchIndex = fname.toLowerCase().indexOf(query),
1527 1523 lnameMatchIndex = lname.toLowerCase().indexOf(query),
1528 1524 nnameMatchIndex = nname.toLowerCase().indexOf(query),
1529 1525 displayfname, displaylname, displaynname;
1530 1526
1531 1527 if (fnameMatchIndex > -1) {
1532 1528 displayfname = highlightMatch(fname, query, fnameMatchIndex);
1533 1529 } else {
1534 1530 displayfname = fname;
1535 1531 }
1536 1532
1537 1533 if (lnameMatchIndex > -1) {
1538 1534 displaylname = highlightMatch(lname, query, lnameMatchIndex);
1539 1535 } else {
1540 1536 displaylname = lname;
1541 1537 }
1542 1538
1543 1539 if (nnameMatchIndex > -1) {
1544 1540 displaynname = "(" + highlightMatch(nname, query, nnameMatchIndex) + ")";
1545 1541 } else {
1546 1542 displaynname = nname ? "(" + nname + ")" : "";
1547 1543 }
1548 1544
1549 1545 return _gravatar(displayfname + " " + displaylname + " " + displaynname, oResultData.gravatar_lnk);
1550 1546 } else {
1551 1547 return '';
1552 1548 }
1553 1549 };
1554 1550
1555 1551 if(ownerAC.itemSelectEvent){
1556 1552 ownerAC.itemSelectEvent.subscribe(function (sType, aArgs) {
1557 1553
1558 1554 var myAC = aArgs[0]; // reference back to the AC instance
1559 1555 var elLI = aArgs[1]; // reference to the selected LI element
1560 1556 var oData = aArgs[2]; // object literal of selected item's result data
1561 1557 //fill the autocomplete with value
1562 1558 if (oData.nname != undefined) {
1563 1559 //users
1564 1560 //Replace the mention name with replaced
1565 1561 var re = new RegExp();
1566 1562 var org = myAC.getInputEl().value;
1567 1563 var chunks = myAC.dataSource.chunks
1568 1564 // replace middle chunk(the search term) with actuall match
1569 1565 chunks[1] = chunks[1].replace('@'+myAC.dataSource.mentionQuery,
1570 1566 '@'+oData.nname+' ');
1571 1567 myAC.getInputEl().value = chunks.join('')
1572 1568 YUD.get(myAC.getInputEl()).focus(); // Y U NO WORK !?
1573 1569 } else {
1574 1570 //groups
1575 1571 myAC.getInputEl().value = oData.grname;
1576 1572 YUD.get('perm_new_member_type').value = 'users_group';
1577 1573 }
1578 1574 });
1579 1575 }
1580 1576
1581 1577 // in this keybuffer we will gather current value of search !
1582 1578 // since we need to get this just when someone does `@` then we do the
1583 1579 // search
1584 1580 ownerAC.dataSource.chunks = [];
1585 1581 ownerAC.dataSource.mentionQuery = null;
1586 1582
1587 1583 ownerAC.get_mention = function(msg, max_pos) {
1588 1584 var org = msg;
1589 1585 var re = new RegExp('(?:^@|\s@)([a-zA-Z0-9]{1}[a-zA-Z0-9\-\_\.]+)$')
1590 1586 var chunks = [];
1591 1587
1592 1588
1593 1589 // cut first chunk until curret pos
1594 1590 var to_max = msg.substr(0, max_pos);
1595 1591 var at_pos = Math.max(0,to_max.lastIndexOf('@')-1);
1596 1592 var msg2 = to_max.substr(at_pos);
1597 1593
1598 1594 chunks.push(org.substr(0,at_pos))// prefix chunk
1599 1595 chunks.push(msg2) // search chunk
1600 1596 chunks.push(org.substr(max_pos)) // postfix chunk
1601 1597
1602 1598 // clean up msg2 for filtering and regex match
1603 1599 var msg2 = msg2.lstrip(' ').lstrip('\n');
1604 1600
1605 1601 if(re.test(msg2)){
1606 1602 var unam = re.exec(msg2)[1];
1607 1603 return [unam, chunks];
1608 1604 }
1609 1605 return [null, null];
1610 1606 };
1611 1607
1612 1608 if (ownerAC.textboxKeyUpEvent){
1613 1609 ownerAC.textboxKeyUpEvent.subscribe(function(type, args){
1614 1610
1615 1611 var ac_obj = args[0];
1616 1612 var currentMessage = args[1];
1617 1613 var currentCaretPosition = args[0]._elTextbox.selectionStart;
1618 1614
1619 1615 var unam = ownerAC.get_mention(currentMessage, currentCaretPosition);
1620 1616 var curr_search = null;
1621 1617 if(unam[0]){
1622 1618 curr_search = unam[0];
1623 1619 }
1624 1620
1625 1621 ownerAC.dataSource.chunks = unam[1];
1626 1622 ownerAC.dataSource.mentionQuery = curr_search;
1627 1623
1628 1624 })
1629 1625 }
1630 1626 return {
1631 1627 ownerDS: ownerDS,
1632 1628 ownerAC: ownerAC,
1633 1629 };
1634 1630 }
1635 1631
1636 1632 var addReviewMember = function(id,fname,lname,nname,gravatar_link){
1637 1633 var members = YUD.get('review_members');
1638 1634 var tmpl = '<li id="reviewer_{2}">'+
1639 1635 '<div class="reviewers_member">'+
1640 1636 '<div class="gravatar"><img alt="gravatar" src="{0}"/> </div>'+
1641 1637 '<div style="float:left">{1}</div>'+
1642 1638 '<input type="hidden" value="{2}" name="review_members" />'+
1643 1639 '<span class="delete_icon action_button" onclick="removeReviewMember({2})"></span>'+
1644 1640 '</div>'+
1645 1641 '</li>' ;
1646 1642 var displayname = "{0} {1} ({2})".format(fname,lname,nname);
1647 1643 var element = tmpl.format(gravatar_link,displayname,id);
1648 1644 // check if we don't have this ID already in
1649 1645 var ids = [];
1650 1646 var _els = YUQ('#review_members li');
1651 1647 for (el in _els){
1652 1648 ids.push(_els[el].id)
1653 1649 }
1654 1650 if(ids.indexOf('reviewer_'+id) == -1){
1655 1651 //only add if it's not there
1656 1652 members.innerHTML += element;
1657 1653 }
1658 1654
1659 1655 }
1660 1656
1661 1657 var removeReviewMember = function(reviewer_id, repo_name, pull_request_id){
1662 1658 var el = YUD.get('reviewer_{0}'.format(reviewer_id));
1663 1659 if (el.parentNode !== undefined){
1664 1660 el.parentNode.removeChild(el);
1665 1661 }
1666 1662 }
1667 1663
1668 1664 var updateReviewers = function(reviewers_ids, repo_name, pull_request_id){
1669 1665 if (reviewers_ids === undefined){
1670 1666 var reviewers_ids = [];
1671 1667 var ids = YUQ('#review_members input');
1672 1668 for(var i=0; i<ids.length;i++){
1673 1669 var id = ids[i].value
1674 1670 reviewers_ids.push(id);
1675 1671 }
1676 1672 }
1677 1673 var url = pyroutes.url('pullrequest_update', {"repo_name":repo_name,
1678 1674 "pull_request_id": pull_request_id});
1679 1675 var postData = {'_method':'put',
1680 1676 'reviewers_ids': reviewers_ids};
1681 1677 var success = function(o){
1682 1678 window.location.reload();
1683 1679 }
1684 1680 ajaxPOST(url,postData,success);
1685 1681 }
1686 1682
1687 1683 var PullRequestAutoComplete = function (divid, cont, users_list, groups_list) {
1688 1684 var myUsers = users_list;
1689 1685 var myGroups = groups_list;
1690 1686
1691 1687 // Define a custom search function for the DataSource of users
1692 1688 var matchUsers = function (sQuery) {
1693 1689 // Case insensitive matching
1694 1690 var query = sQuery.toLowerCase();
1695 1691 var i = 0;
1696 1692 var l = myUsers.length;
1697 1693 var matches = [];
1698 1694
1699 1695 // Match against each name of each contact
1700 1696 for (; i < l; i++) {
1701 1697 contact = myUsers[i];
1702 1698 if (((contact.fname+"").toLowerCase().indexOf(query) > -1) ||
1703 1699 ((contact.lname+"").toLowerCase().indexOf(query) > -1) ||
1704 1700 ((contact.nname) && ((contact.nname).toLowerCase().indexOf(query) > -1))) {
1705 1701 matches[matches.length] = contact;
1706 1702 }
1707 1703 }
1708 1704 return matches;
1709 1705 };
1710 1706
1711 1707 // Define a custom search function for the DataSource of userGroups
1712 1708 var matchGroups = function (sQuery) {
1713 1709 // Case insensitive matching
1714 1710 var query = sQuery.toLowerCase();
1715 1711 var i = 0;
1716 1712 var l = myGroups.length;
1717 1713 var matches = [];
1718 1714
1719 1715 // Match against each name of each contact
1720 1716 for (; i < l; i++) {
1721 1717 matched_group = myGroups[i];
1722 1718 if (matched_group.grname.toLowerCase().indexOf(query) > -1) {
1723 1719 matches[matches.length] = matched_group;
1724 1720 }
1725 1721 }
1726 1722 return matches;
1727 1723 };
1728 1724
1729 1725 //match all
1730 1726 var matchAll = function (sQuery) {
1731 1727 u = matchUsers(sQuery);
1732 1728 return u
1733 1729 };
1734 1730
1735 1731 // DataScheme for owner
1736 1732 var ownerDS = new YAHOO.util.FunctionDataSource(matchUsers);
1737 1733
1738 1734 ownerDS.responseSchema = {
1739 1735 fields: ["id", "fname", "lname", "nname", "gravatar_lnk"]
1740 1736 };
1741 1737
1742 1738 // Instantiate AutoComplete for mentions
1743 1739 var reviewerAC = new YAHOO.widget.AutoComplete(divid, cont, ownerDS);
1744 1740 reviewerAC.useShadow = false;
1745 1741 reviewerAC.resultTypeList = false;
1746 1742 reviewerAC.suppressInputUpdate = true;
1747 1743 reviewerAC.animVert = false;
1748 1744 reviewerAC.animHoriz = false;
1749 1745 reviewerAC.animSpeed = 0.1;
1750 1746
1751 1747 // Helper highlight function for the formatter
1752 1748 var highlightMatch = function (full, snippet, matchindex) {
1753 1749 return full.substring(0, matchindex)
1754 1750 + "<span class='match'>"
1755 1751 + full.substr(matchindex, snippet.length)
1756 1752 + "</span>" + full.substring(matchindex + snippet.length);
1757 1753 };
1758 1754
1759 1755 // Custom formatter to highlight the matching letters
1760 1756 reviewerAC.formatResult = function (oResultData, sQuery, sResultMatch) {
1761 1757 var org_sQuery = sQuery;
1762 1758 if(this.dataSource.mentionQuery != null){
1763 1759 sQuery = this.dataSource.mentionQuery;
1764 1760 }
1765 1761
1766 1762 var query = sQuery.toLowerCase();
1767 1763 var _gravatar = function(res, em, group){
1768 1764 if (group !== undefined){
1769 1765 em = '/images/icons/group.png'
1770 1766 }
1771 1767 tmpl = '<div class="ac-container-wrap"><img class="perm-gravatar-ac" src="{0}"/>{1}</div>'
1772 1768 return tmpl.format(em,res)
1773 1769 }
1774 1770 if (oResultData.nname != undefined) {
1775 1771 var fname = oResultData.fname || "";
1776 1772 var lname = oResultData.lname || "";
1777 1773 var nname = oResultData.nname;
1778 1774
1779 1775 // Guard against null value
1780 1776 var fnameMatchIndex = fname.toLowerCase().indexOf(query),
1781 1777 lnameMatchIndex = lname.toLowerCase().indexOf(query),
1782 1778 nnameMatchIndex = nname.toLowerCase().indexOf(query),
1783 1779 displayfname, displaylname, displaynname;
1784 1780
1785 1781 if (fnameMatchIndex > -1) {
1786 1782 displayfname = highlightMatch(fname, query, fnameMatchIndex);
1787 1783 } else {
1788 1784 displayfname = fname;
1789 1785 }
1790 1786
1791 1787 if (lnameMatchIndex > -1) {
1792 1788 displaylname = highlightMatch(lname, query, lnameMatchIndex);
1793 1789 } else {
1794 1790 displaylname = lname;
1795 1791 }
1796 1792
1797 1793 if (nnameMatchIndex > -1) {
1798 1794 displaynname = "(" + highlightMatch(nname, query, nnameMatchIndex) + ")";
1799 1795 } else {
1800 1796 displaynname = nname ? "(" + nname + ")" : "";
1801 1797 }
1802 1798
1803 1799 return _gravatar(displayfname + " " + displaylname + " " + displaynname, oResultData.gravatar_lnk);
1804 1800 } else {
1805 1801 return '';
1806 1802 }
1807 1803 };
1808 1804
1809 1805 //members cache to catch duplicates
1810 1806 reviewerAC.dataSource.cache = [];
1811 1807 // hack into select event
1812 1808 if(reviewerAC.itemSelectEvent){
1813 1809 reviewerAC.itemSelectEvent.subscribe(function (sType, aArgs) {
1814 1810
1815 1811 var myAC = aArgs[0]; // reference back to the AC instance
1816 1812 var elLI = aArgs[1]; // reference to the selected LI element
1817 1813 var oData = aArgs[2]; // object literal of selected item's result data
1818 1814
1819 1815 //fill the autocomplete with value
1820 1816
1821 1817 if (oData.nname != undefined) {
1822 1818 addReviewMember(oData.id, oData.fname, oData.lname, oData.nname,
1823 1819 oData.gravatar_lnk);
1824 1820 myAC.dataSource.cache.push(oData.id);
1825 1821 YUD.get('user').value = ''
1826 1822 }
1827 1823 });
1828 1824 }
1829 1825 return {
1830 1826 ownerDS: ownerDS,
1831 1827 reviewerAC: reviewerAC,
1832 1828 };
1833 1829 }
1834 1830
1835 1831 /**
1836 1832 * QUICK REPO MENU
1837 1833 */
1838 1834 var quick_repo_menu = function(){
1839 1835 YUE.on(YUQ('.quick_repo_menu'),'mouseenter',function(e){
1840 1836 var menu = e.currentTarget.firstElementChild.firstElementChild;
1841 1837 if(YUD.hasClass(menu,'hidden')){
1842 1838 YUD.replaceClass(e.currentTarget,'hidden', 'active');
1843 1839 YUD.replaceClass(menu, 'hidden', 'active');
1844 1840 }
1845 1841 })
1846 1842 YUE.on(YUQ('.quick_repo_menu'),'mouseleave',function(e){
1847 1843 var menu = e.currentTarget.firstElementChild.firstElementChild;
1848 1844 if(YUD.hasClass(menu,'active')){
1849 1845 YUD.replaceClass(e.currentTarget, 'active', 'hidden');
1850 1846 YUD.replaceClass(menu, 'active', 'hidden');
1851 1847 }
1852 1848 })
1853 1849 };
1854 1850
1855 1851
1856 1852 /**
1857 1853 * TABLE SORTING
1858 1854 */
1859 1855
1860 1856 // returns a node from given html;
1861 1857 var fromHTML = function(html){
1862 1858 var _html = document.createElement('element');
1863 1859 _html.innerHTML = html;
1864 1860 return _html;
1865 1861 }
1866 1862 var get_rev = function(node){
1867 1863 var n = node.firstElementChild.firstElementChild;
1868 1864
1869 1865 if (n===null){
1870 1866 return -1
1871 1867 }
1872 1868 else{
1873 1869 out = n.firstElementChild.innerHTML.split(':')[0].replace('r','');
1874 1870 return parseInt(out);
1875 1871 }
1876 1872 }
1877 1873
1878 1874 var get_name = function(node){
1879 1875 var name = node.firstElementChild.children[2].innerHTML;
1880 1876 return name
1881 1877 }
1882 1878 var get_group_name = function(node){
1883 1879 var name = node.firstElementChild.children[1].innerHTML;
1884 1880 return name
1885 1881 }
1886 1882 var get_date = function(node){
1887 1883 var date_ = YUD.getAttribute(node.firstElementChild,'date');
1888 1884 return date_
1889 1885 }
1890 1886
1891 1887 var get_age = function(node){
1892 1888 return node
1893 1889 }
1894 1890
1895 1891 var get_link = function(node){
1896 1892 return node.firstElementChild.text;
1897 1893 }
1898 1894
1899 1895 var revisionSort = function(a, b, desc, field) {
1900 1896
1901 1897 var a_ = fromHTML(a.getData(field));
1902 1898 var b_ = fromHTML(b.getData(field));
1903 1899
1904 1900 // extract revisions from string nodes
1905 1901 a_ = get_rev(a_)
1906 1902 b_ = get_rev(b_)
1907 1903
1908 1904 var comp = YAHOO.util.Sort.compare;
1909 1905 var compState = comp(a_, b_, desc);
1910 1906 return compState;
1911 1907 };
1912 1908 var ageSort = function(a, b, desc, field) {
1913 1909 var a_ = fromHTML(a.getData(field));
1914 1910 var b_ = fromHTML(b.getData(field));
1915 1911
1916 1912 // extract name from table
1917 1913 a_ = get_date(a_)
1918 1914 b_ = get_date(b_)
1919 1915
1920 1916 var comp = YAHOO.util.Sort.compare;
1921 1917 var compState = comp(a_, b_, desc);
1922 1918 return compState;
1923 1919 };
1924 1920
1925 1921 var lastLoginSort = function(a, b, desc, field) {
1926 1922 var a_ = a.getData('last_login_raw') || 0;
1927 1923 var b_ = b.getData('last_login_raw') || 0;
1928 1924
1929 1925 var comp = YAHOO.util.Sort.compare;
1930 1926 var compState = comp(a_, b_, desc);
1931 1927 return compState;
1932 1928 };
1933 1929
1934 1930 var nameSort = function(a, b, desc, field) {
1935 1931 var a_ = fromHTML(a.getData(field));
1936 1932 var b_ = fromHTML(b.getData(field));
1937 1933
1938 1934 // extract name from table
1939 1935 a_ = get_name(a_)
1940 1936 b_ = get_name(b_)
1941 1937
1942 1938 var comp = YAHOO.util.Sort.compare;
1943 1939 var compState = comp(a_, b_, desc);
1944 1940 return compState;
1945 1941 };
1946 1942
1947 1943 var permNameSort = function(a, b, desc, field) {
1948 1944 var a_ = fromHTML(a.getData(field));
1949 1945 var b_ = fromHTML(b.getData(field));
1950 1946 // extract name from table
1951 1947
1952 1948 a_ = a_.children[0].innerHTML;
1953 1949 b_ = b_.children[0].innerHTML;
1954 1950
1955 1951 var comp = YAHOO.util.Sort.compare;
1956 1952 var compState = comp(a_, b_, desc);
1957 1953 return compState;
1958 1954 };
1959 1955
1960 1956 var groupNameSort = function(a, b, desc, field) {
1961 1957 var a_ = fromHTML(a.getData(field));
1962 1958 var b_ = fromHTML(b.getData(field));
1963 1959
1964 1960 // extract name from table
1965 1961 a_ = get_group_name(a_)
1966 1962 b_ = get_group_name(b_)
1967 1963
1968 1964 var comp = YAHOO.util.Sort.compare;
1969 1965 var compState = comp(a_, b_, desc);
1970 1966 return compState;
1971 1967 };
1972 1968 var dateSort = function(a, b, desc, field) {
1973 1969 var a_ = fromHTML(a.getData(field));
1974 1970 var b_ = fromHTML(b.getData(field));
1975 1971
1976 1972 // extract name from table
1977 1973 a_ = get_date(a_)
1978 1974 b_ = get_date(b_)
1979 1975
1980 1976 var comp = YAHOO.util.Sort.compare;
1981 1977 var compState = comp(a_, b_, desc);
1982 1978 return compState;
1983 1979 };
1984 1980
1985 1981 var usernamelinkSort = function(a, b, desc, field) {
1986 1982 var a_ = fromHTML(a.getData(field));
1987 1983 var b_ = fromHTML(b.getData(field));
1988 1984
1989 1985 // extract url text from string nodes
1990 1986 a_ = get_link(a_)
1991 1987 b_ = get_link(b_)
1992 1988 var comp = YAHOO.util.Sort.compare;
1993 1989 var compState = comp(a_, b_, desc);
1994 1990 return compState;
1995 1991 }
1996 1992
1997 1993 var addPermAction = function(_html, users_list, groups_list){
1998 1994 var elmts = YUD.getElementsByClassName('last_new_member');
1999 1995 var last_node = elmts[elmts.length-1];
2000 1996 if (last_node){
2001 1997 var next_id = (YUD.getElementsByClassName('new_members')).length;
2002 1998 _html = _html.format(next_id);
2003 1999 last_node.innerHTML = _html;
2004 2000 YUD.setStyle(last_node, 'display', '');
2005 2001 YUD.removeClass(last_node, 'last_new_member');
2006 2002 MembersAutoComplete("perm_new_member_name_"+next_id,
2007 2003 "perm_container_"+next_id, users_list, groups_list);
2008 2004 //create new last NODE
2009 2005 var el = document.createElement('tr');
2010 2006 el.id = 'add_perm_input';
2011 2007 YUD.addClass(el,'last_new_member');
2012 2008 YUD.addClass(el,'new_members');
2013 2009 YUD.insertAfter(el, last_node);
2014 2010 }
2015 2011 }
2016 2012
2017 2013 /* Multi selectors */
2018 2014
2019 2015 var MultiSelectWidget = function(selected_id, available_id, form_id){
2020 2016
2021 2017
2022 2018 //definition of containers ID's
2023 2019 var selected_container = selected_id;
2024 2020 var available_container = available_id;
2025 2021
2026 2022 //temp container for selected storage.
2027 2023 var cache = new Array();
2028 2024 var av_cache = new Array();
2029 2025 var c = YUD.get(selected_container);
2030 2026 var ac = YUD.get(available_container);
2031 2027
2032 2028 //get only selected options for further fullfilment
2033 2029 for(var i = 0;node =c.options[i];i++){
2034 2030 if(node.selected){
2035 2031 //push selected to my temp storage left overs :)
2036 2032 cache.push(node);
2037 2033 }
2038 2034 }
2039 2035
2040 2036 //get all available options to cache
2041 2037 for(var i = 0;node =ac.options[i];i++){
2042 2038 //push selected to my temp storage left overs :)
2043 2039 av_cache.push(node);
2044 2040 }
2045 2041
2046 2042 //fill available only with those not in chosen
2047 2043 ac.options.length=0;
2048 2044 tmp_cache = new Array();
2049 2045
2050 2046 for(var i = 0;node = av_cache[i];i++){
2051 2047 var add = true;
2052 2048 for(var i2 = 0;node_2 = cache[i2];i2++){
2053 2049 if(node.value == node_2.value){
2054 2050 add=false;
2055 2051 break;
2056 2052 }
2057 2053 }
2058 2054 if(add){
2059 2055 tmp_cache.push(new Option(node.text, node.value, false, false));
2060 2056 }
2061 2057 }
2062 2058
2063 2059 for(var i = 0;node = tmp_cache[i];i++){
2064 2060 ac.options[i] = node;
2065 2061 }
2066 2062
2067 2063 function prompts_action_callback(e){
2068 2064
2069 2065 var chosen = YUD.get(selected_container);
2070 2066 var available = YUD.get(available_container);
2071 2067
2072 2068 //get checked and unchecked options from field
2073 2069 function get_checked(from_field){
2074 2070 //temp container for storage.
2075 2071 var sel_cache = new Array();
2076 2072 var oth_cache = new Array();
2077 2073
2078 2074 for(var i = 0;node = from_field.options[i];i++){
2079 2075 if(node.selected){
2080 2076 //push selected fields :)
2081 2077 sel_cache.push(node);
2082 2078 }
2083 2079 else{
2084 2080 oth_cache.push(node)
2085 2081 }
2086 2082 }
2087 2083
2088 2084 return [sel_cache,oth_cache]
2089 2085 }
2090 2086
2091 2087 //fill the field with given options
2092 2088 function fill_with(field,options){
2093 2089 //clear firtst
2094 2090 field.options.length=0;
2095 2091 for(var i = 0;node = options[i];i++){
2096 2092 field.options[i]=new Option(node.text, node.value,
2097 2093 false, false);
2098 2094 }
2099 2095
2100 2096 }
2101 2097 //adds to current field
2102 2098 function add_to(field,options){
2103 2099 for(var i = 0;node = options[i];i++){
2104 2100 field.appendChild(new Option(node.text, node.value,
2105 2101 false, false));
2106 2102 }
2107 2103 }
2108 2104
2109 2105 // add action
2110 2106 if (this.id=='add_element'){
2111 2107 var c = get_checked(available);
2112 2108 add_to(chosen,c[0]);
2113 2109 fill_with(available,c[1]);
2114 2110 }
2115 2111 // remove action
2116 2112 if (this.id=='remove_element'){
2117 2113 var c = get_checked(chosen);
2118 2114 add_to(available,c[0]);
2119 2115 fill_with(chosen,c[1]);
2120 2116 }
2121 2117 // add all elements
2122 2118 if(this.id=='add_all_elements'){
2123 2119 for(var i=0; node = available.options[i];i++){
2124 2120 chosen.appendChild(new Option(node.text,
2125 2121 node.value, false, false));
2126 2122 }
2127 2123 available.options.length = 0;
2128 2124 }
2129 2125 //remove all elements
2130 2126 if(this.id=='remove_all_elements'){
2131 2127 for(var i=0; node = chosen.options[i];i++){
2132 2128 available.appendChild(new Option(node.text,
2133 2129 node.value, false, false));
2134 2130 }
2135 2131 chosen.options.length = 0;
2136 2132 }
2137 2133
2138 2134 }
2139 2135
2140 2136 YUE.addListener(['add_element','remove_element',
2141 2137 'add_all_elements','remove_all_elements'],'click',
2142 2138 prompts_action_callback)
2143 2139 if (form_id !== undefined) {
2144 2140 YUE.addListener(form_id,'submit',function(){
2145 2141 var chosen = YUD.get(selected_container);
2146 2142 for (var i = 0; i < chosen.options.length; i++) {
2147 2143 chosen.options[i].selected = 'selected';
2148 2144 }
2149 2145 });
2150 2146 }
2151 2147 }
2152 2148
2153 2149
2154 2150 // global hooks after DOM is loaded
2155 2151
2156 2152 YUE.onDOMReady(function(){
2157 2153 YUE.on(YUQ('.diff-collapse-button'), 'click', function(e){
2158 2154 var button = e.currentTarget;
2159 2155 var t = YUD.get(button).getAttribute('target');
2160 2156 console.log(t);
2161 2157 if(YUD.hasClass(t, 'hidden')){
2162 2158 YUD.removeClass(t, 'hidden');
2163 2159 YUD.get(button).innerHTML = "&uarr; {0} &uarr;".format(_TM['Collapse diff']);
2164 2160 }
2165 2161 else if(!YUD.hasClass(t, 'hidden')){
2166 2162 YUD.addClass(t, 'hidden');
2167 2163 YUD.get(button).innerHTML = "&darr; {0} &darr;".format(_TM['Expand diff']);
2168 2164 }
2169 2165 });
2170 2166
2171 2167
2172 2168
2173 2169 });
2174 2170
@@ -1,142 +1,141 b''
1 1 ## -*- coding: utf-8 -*-
2 2 <%inherit file="/base/base.html"/>
3 3
4 4 <%def name="title()">
5 5 ${_('Repositories administration')} &middot; ${c.rhodecode_name}
6 6 </%def>
7 7
8 8 <%def name="breadcrumbs_links()">
9 <input class="q_filter_box" id="q_filter" size="15" type="text" name="filter" value="${_('quick filter...')}"/> ${h.link_to(_('Admin'),h.url('admin_home'))} &raquo; <span id="repo_count">0</span> ${_('repositories')}
9 <input class="q_filter_box" id="q_filter" size="15" type="text" name="filter" placeholder="${_('quick filter...')}" value=""/> ${h.link_to(_('Admin'),h.url('admin_home'))} &raquo; <span id="repo_count">0</span> ${_('repositories')}
10 10 </%def>
11 11 <%def name="page_nav()">
12 12 ${self.menu('admin')}
13 13 </%def>
14 14 <%def name="main()">
15 15 <div class="box">
16 16
17 17 <div class="title">
18 18 ${self.breadcrumbs()}
19 19 <ul class="links">
20 20 <li>
21 21 <span>${h.link_to(_(u'Add repository'),h.url('new_repo'))}</span>
22 22 </li>
23 23 </ul>
24 24 </div>
25 25 <div class="table yui-skin-sam" id="repos_list_wrap"></div>
26 26 <div id="user-paginator" style="padding: 0px 0px 0px 20px"></div>
27 27
28 28
29 29 </div>
30 30 <script>
31 31 var url = "${h.url('formatted_users', format='json')}";
32 32 var data = ${c.data|n};
33 33 var myDataSource = new YAHOO.util.DataSource(data);
34 34 myDataSource.responseType = YAHOO.util.DataSource.TYPE_JSON;
35 35
36 36 myDataSource.responseSchema = {
37 37 resultsList: "records",
38 38 fields: [
39 39 {key:"menu"},
40 40 {key:"raw_name"},
41 41 {key:"name"},
42 42 {key:"desc"},
43 43 {key:"last_changeset"},
44 44 {key:"owner"},
45 45 {key:"action"},
46 46 ]
47 47 };
48 48 myDataSource.doBeforeCallback = function(req,raw,res,cb) {
49 49 // This is the filter function
50 50 var data = res.results || [],
51 51 filtered = [],
52 52 i,l;
53 53
54 54 if (req) {
55 55 req = req.toLowerCase();
56 56 for (i = 0; i<data.length; i++) {
57 57 var pos = data[i].raw_name.toLowerCase().indexOf(req)
58 58 if (pos != -1) {
59 59 filtered.push(data[i]);
60 60 }
61 61 }
62 62 res.results = filtered;
63 63 }
64 64 YUD.get('repo_count').innerHTML = res.results.length;
65 65 return res;
66 66 }
67 67
68 68 // main table sorting
69 69 var myColumnDefs = [
70 70 {key:"menu",label:"",sortable:false,className:"quick_repo_menu hidden"},
71 71 {key:"name",label:"${_('Name')}",sortable:true,
72 72 sortOptions: { sortFunction: nameSort }},
73 73 {key:"desc",label:"${_('Description')}",sortable:true},
74 74 {key:"last_changeset",label:"${_('Tip')}",sortable:true,
75 75 sortOptions: { sortFunction: revisionSort }},
76 76 {key:"owner",label:"${_('Owner')}",sortable:true},
77 77 {key:"action",label:"${_('Action')}",sortable:false},
78 78 ];
79 79
80 80 var myDataTable = new YAHOO.widget.DataTable("repos_list_wrap", myColumnDefs, myDataSource,{
81 81 sortedBy:{key:"name",dir:"asc"},
82 82 paginator: new YAHOO.widget.Paginator({
83 83 rowsPerPage: 25,
84 84 alwaysVisible: false,
85 85 template : "{PreviousPageLink} {FirstPageLink} {PageLinks} {LastPageLink} {NextPageLink}",
86 86 pageLinks: 5,
87 87 containerClass: 'pagination-wh',
88 88 currentPageClass: 'pager_curpage',
89 89 pageLinkClass: 'pager_link',
90 90 nextPageLinkLabel: '&gt;',
91 91 previousPageLinkLabel: '&lt;',
92 92 firstPageLinkLabel: '&lt;&lt;',
93 93 lastPageLinkLabel: '&gt;&gt;',
94 94 containers:['user-paginator']
95 95 }),
96 96
97 97 MSG_SORTASC:"${_('Click to sort ascending')}",
98 98 MSG_SORTDESC:"${_('Click to sort descending')}",
99 99 MSG_EMPTY:"${_('No records found.')}",
100 100 MSG_ERROR:"${_('Data error.')}",
101 101 MSG_LOADING:"${_('Loading...')}",
102 102 }
103 103 );
104 104 myDataTable.subscribe('postRenderEvent',function(oArgs) {
105 105 tooltip_activate();
106 106 quick_repo_menu();
107 107 });
108 108
109 109 var filterTimeout = null;
110 110
111 111 updateFilter = function () {
112 112 // Reset timeout
113 113 filterTimeout = null;
114 114
115 115 // Reset sort
116 116 var state = myDataTable.getState();
117 117 state.sortedBy = {key:'name', dir:YAHOO.widget.DataTable.CLASS_ASC};
118 118
119 119 // Get filtered data
120 120 myDataSource.sendRequest(YUD.get('q_filter').value,{
121 121 success : myDataTable.onDataReturnInitializeTable,
122 122 failure : myDataTable.onDataReturnInitializeTable,
123 123 scope : myDataTable,
124 124 argument: state
125 125 });
126 126
127 127 };
128 128 YUE.on('q_filter','click',function(){
129 129 if(!YUD.hasClass('q_filter', 'loaded')){
130 YUD.get('q_filter').value = '';
131 130 //TODO: load here full list later to do search within groups
132 131 YUD.addClass('q_filter', 'loaded');
133 132 }
134 133 });
135 134
136 135 YUE.on('q_filter','keyup',function (e) {
137 136 clearTimeout(filterTimeout);
138 137 filterTimeout = setTimeout(updateFilter,600);
139 138 });
140 139 </script>
141 140
142 141 </%def>
@@ -1,284 +1,283 b''
1 1 ## -*- coding: utf-8 -*-
2 2 <%inherit file="/base/base.html"/>
3 3
4 4 <%def name="title()">
5 5 ${_('My account')} ${c.rhodecode_user.username} &middot; ${c.rhodecode_name}
6 6 </%def>
7 7
8 8 <%def name="breadcrumbs_links()">
9 9 ${_('My Account')}
10 10 </%def>
11 11
12 12 <%def name="page_nav()">
13 13 ${self.menu('admin')}
14 14 </%def>
15 15
16 16 <%def name="main()">
17 17
18 18 <div class="box box-left">
19 19 <!-- box / title -->
20 20 <div class="title">
21 21 ${self.breadcrumbs()}
22 22 </div>
23 23 <!-- end box / title -->
24 24 ${c.form|n}
25 25 </div>
26 26
27 27 <div class="box box-right">
28 28 <!-- box / title -->
29 29 <div class="title">
30 30 <h5>
31 <input class="q_filter_box" id="q_filter" size="15" type="text" name="filter" value="${_('quick filter...')}" style="display: none"/>
31 <input class="q_filter_box" id="q_filter" size="15" type="text" name="filter" placeholder="${_('quick filter...')}" value="" style="display: none"/>
32 32 </h5>
33 33 <ul class="links" style="color:#DADADA">
34 34 <li>
35 35 <span><a id="show_perms" class="link-white current" href="#perms">${_('My permissions')}</a> </span>
36 36 </li>
37 37 <li>
38 38 <span><a id="show_my" class="link-white" href="#my">${_('My repos')}</a> </span>
39 39 </li>
40 40 <li>
41 41 <span><a id="show_pullrequests" class="link-white" href="#pullrequests">${_('My pull requests')}</a> </span>
42 42 </li>
43 43 </ul>
44 44 </div>
45 45 <!-- end box / title -->
46 46 <div id="perms_container">
47 47 <div id="perms" class="table">
48 48 %for section in sorted(c.rhodecode_user.permissions.keys()):
49 49 <div class="perms_section_head">${section.replace("_"," ").capitalize()}</div>
50 50
51 51 <div id='tbl_list_wrap_${section}' class="yui-skin-sam">
52 52 <table id="tbl_list_${section}">
53 53 <thead>
54 54 <tr>
55 55 <th class="left">${_('Name')}</th>
56 56 <th class="left">${_('Permission')}</th>
57 57 </thead>
58 58 <tbody>
59 59 %for k in sorted(c.rhodecode_user.permissions[section], key=lambda s: s.lower):
60 60 <%
61 61 if section != 'global':
62 62 section_perm = c.rhodecode_user.permissions[section].get(k)
63 63 _perm = section_perm.split('.')[-1]
64 64 else:
65 65 _perm = section_perm = None
66 66 %>
67 67 %if _perm not in ['none']:
68 68 <tr>
69 69 <td>
70 70 %if section == 'repositories':
71 71 <a href="${h.url('summary_home',repo_name=k)}">${k}</a>
72 72 %elif section == 'repositories_groups':
73 73 <a href="${h.url('repos_group_home',group_name=k)}">${k}</a>
74 74 %else:
75 75 ${k}
76 76 %endif
77 77 </td>
78 78 <td>
79 79 %if section == 'global':
80 80 ${h.boolicon(True)}
81 81 %else:
82 82 <span class="perm_tag ${_perm}">${section_perm}</span>
83 83 %endif
84 84 </td>
85 85 </tr>
86 86 %endif
87 87 %endfor
88 88 </tbody>
89 89 </table>
90 90 </div>
91 91 %endfor
92 92 </div>
93 93 </div>
94 94 <div id="my_container" style="display:none">
95 95 <div class="table yui-skin-sam" id="repos_list_wrap"></div>
96 96 <div id="user-paginator" style="padding: 0px 0px 0px 20px"></div>
97 97 </div>
98 98 <div id="pullrequests_container" class="table" style="display:none">
99 99 ## loaded via AJAX
100 100 ${_('Loading...')}
101 101 </div>
102 102 </div>
103 103
104 104 <script type="text/javascript">
105 105 pyroutes.register('admin_settings_my_pullrequests', "${url('admin_settings_my_pullrequests')}", []);
106 106
107 107 var show_perms = function(e){
108 108 YUD.addClass('show_perms', 'current');
109 109 YUD.removeClass('show_my','current');
110 110 YUD.removeClass('show_pullrequests','current');
111 111
112 112 YUD.setStyle('my_container','display','none');
113 113 YUD.setStyle('pullrequests_container','display','none');
114 114 YUD.setStyle('perms_container','display','');
115 115 YUD.setStyle('q_filter','display','none');
116 116 }
117 117 YUE.on('show_perms','click',function(e){
118 118 show_perms();
119 119 })
120 120
121 121 var show_my = function(e){
122 122 YUD.addClass('show_my', 'current');
123 123 YUD.removeClass('show_perms','current');
124 124 YUD.removeClass('show_pullrequests','current');
125 125
126 126 YUD.setStyle('perms_container','display','none');
127 127 YUD.setStyle('pullrequests_container','display','none');
128 128 YUD.setStyle('my_container','display','');
129 129 YUD.setStyle('q_filter','display','');
130 130 if(!YUD.hasClass('show_my', 'loaded')){
131 131 table_renderer(${c.data |n});
132 132 YUD.addClass('show_my', 'loaded');
133 133 }
134 134 }
135 135 YUE.on('show_my','click',function(e){
136 136 show_my(e);
137 137 })
138 138
139 139 var show_pullrequests = function(e){
140 140 YUD.addClass('show_pullrequests', 'current');
141 141 YUD.removeClass('show_my','current');
142 142 YUD.removeClass('show_perms','current');
143 143
144 144 YUD.setStyle('my_container','display','none');
145 145 YUD.setStyle('perms_container','display','none');
146 146 YUD.setStyle('pullrequests_container','display','');
147 147 YUD.setStyle('q_filter','display','none');
148 148
149 149 var url = pyroutes.url('admin_settings_my_pullrequests');
150 150 if(YUD.get('show_closed') && YUD.get('show_closed').checked) {
151 151 var url = pyroutes.url('admin_settings_my_pullrequests', {'pr_show_closed': '1'});
152 152 }
153 153 ypjax(url, 'pullrequests_container', function(){
154 154 YUE.on('show_closed','change',function (e) {
155 155 show_pullrequests(e);
156 156 });
157 157 });
158 158 }
159 159 YUE.on('show_pullrequests','click',function(e){
160 160 show_pullrequests(e)
161 161 })
162 162
163 163 var tabs = {
164 164 'perms': show_perms,
165 165 'my': show_my,
166 166 'pullrequests': show_pullrequests
167 167 }
168 168 var url = location.href.split('#');
169 169 if (url[1]) {
170 170 //We have a hash
171 171 var tabHash = url[1];
172 172 var func = tabs[tabHash]
173 173 if (func){
174 174 func();
175 175 }
176 176 }
177 177
178 178 function table_renderer(data){
179 179 var myDataSource = new YAHOO.util.DataSource(data);
180 180 myDataSource.responseType = YAHOO.util.DataSource.TYPE_JSON;
181 181
182 182 myDataSource.responseSchema = {
183 183 resultsList: "records",
184 184 fields: [
185 185 {key:"menu"},
186 186 {key:"raw_name"},
187 187 {key:"name"},
188 188 {key:"last_changeset"},
189 189 {key:"action"},
190 190 ]
191 191 };
192 192 myDataSource.doBeforeCallback = function(req,raw,res,cb) {
193 193 // This is the filter function
194 194 var data = res.results || [],
195 195 filtered = [],
196 196 i,l;
197 197
198 198 if (req) {
199 199 req = req.toLowerCase();
200 200 for (i = 0; i<data.length; i++) {
201 201 var pos = data[i].raw_name.toLowerCase().indexOf(req)
202 202 if (pos != -1) {
203 203 filtered.push(data[i]);
204 204 }
205 205 }
206 206 res.results = filtered;
207 207 }
208 208 return res;
209 209 }
210 210
211 211 // main table sorting
212 212 var myColumnDefs = [
213 213 {key:"menu",label:"",sortable:false,className:"quick_repo_menu hidden"},
214 214 {key:"name",label:"${_('Name')}",sortable:true,
215 215 sortOptions: { sortFunction: nameSort }},
216 216 {key:"last_changeset",label:"${_('Tip')}",sortable:true,
217 217 sortOptions: { sortFunction: revisionSort }},
218 218 {key:"action",label:"${_('Action')}",sortable:false},
219 219 ];
220 220
221 221 var myDataTable = new YAHOO.widget.DataTable("repos_list_wrap", myColumnDefs, myDataSource,{
222 222 sortedBy:{key:"name",dir:"asc"},
223 223 paginator: new YAHOO.widget.Paginator({
224 224 rowsPerPage: 50,
225 225 alwaysVisible: false,
226 226 template : "{PreviousPageLink} {FirstPageLink} {PageLinks} {LastPageLink} {NextPageLink}",
227 227 pageLinks: 5,
228 228 containerClass: 'pagination-wh',
229 229 currentPageClass: 'pager_curpage',
230 230 pageLinkClass: 'pager_link',
231 231 nextPageLinkLabel: '&gt;',
232 232 previousPageLinkLabel: '&lt;',
233 233 firstPageLinkLabel: '&lt;&lt;',
234 234 lastPageLinkLabel: '&gt;&gt;',
235 235 containers:['user-paginator']
236 236 }),
237 237
238 238 MSG_SORTASC:"${_('Click to sort ascending')}",
239 239 MSG_SORTDESC:"${_('Click to sort descending')}",
240 240 MSG_EMPTY:"${_('No records found.')}",
241 241 MSG_ERROR:"${_('Data error.')}",
242 242 MSG_LOADING:"${_('Loading...')}",
243 243 }
244 244 );
245 245 myDataTable.subscribe('postRenderEvent',function(oArgs) {
246 246 tooltip_activate();
247 247 quick_repo_menu();
248 248 });
249 249
250 250 var filterTimeout = null;
251 251
252 252 updateFilter = function() {
253 253 // Reset timeout
254 254 filterTimeout = null;
255 255
256 256 // Reset sort
257 257 var state = myDataTable.getState();
258 258 state.sortedBy = {key:'name', dir:YAHOO.widget.DataTable.CLASS_ASC};
259 259
260 260 // Get filtered data
261 261 myDataSource.sendRequest(YUD.get('q_filter').value,{
262 262 success : myDataTable.onDataReturnInitializeTable,
263 263 failure : myDataTable.onDataReturnInitializeTable,
264 264 scope : myDataTable,
265 265 argument: state
266 266 });
267 267
268 268 };
269 269 YUE.on('q_filter','click',function(){
270 270 if(!YUD.hasClass('q_filter', 'loaded')){
271 YUD.get('q_filter').value = '';
272 271 //TODO: load here full list later to do search within groups
273 272 YUD.addClass('q_filter', 'loaded');
274 273 }
275 274 });
276 275
277 276 YUE.on('q_filter','keyup',function (e) {
278 277 clearTimeout(filterTimeout);
279 278 filterTimeout = setTimeout(updateFilter,600);
280 279 });
281 280
282 281 }
283 282 </script>
284 283 </%def>
@@ -1,147 +1,144 b''
1 1 ## -*- coding: utf-8 -*-
2 2 <%inherit file="/base/base.html"/>
3 3
4 4 <%def name="title()">
5 5 ${_('Users administration')} &middot; ${c.rhodecode_name}
6 6 </%def>
7 7
8 8 <%def name="breadcrumbs_links()">
9 <input class="q_filter_box" id="q_filter" size="15" type="text" name="filter" value="${_('quick filter...')}"/> ${h.link_to(_('Admin'),h.url('admin_home'))} &raquo; <span id="user_count">0</span> ${_('users')}
9 <input class="q_filter_box" id="q_filter" size="15" type="text" name="filter" placeholder="${_('quick filter...')}" value=""/> ${h.link_to(_('Admin'),h.url('admin_home'))} &raquo; <span id="user_count">0</span> ${_('users')}
10 10 </%def>
11 11
12 12 <%def name="page_nav()">
13 13 ${self.menu('admin')}
14 14 </%def>
15 15
16 16 <%def name="main()">
17 17 <div class="box">
18 18 <!-- box / title -->
19 19 <div class="title">
20 20 ${self.breadcrumbs()}
21 21 <ul class="links">
22 22 <li>
23 23 <span>${h.link_to(_(u'Add new user'),h.url('new_user'))}</span>
24 24 </li>
25 25 </ul>
26 26 </div>
27 27 <!-- end box / title -->
28 28 <div class="table yui-skin-sam" id="users_list_wrap"></div>
29 29 <div id="user-paginator" style="padding: 0px 0px 0px 20px"></div>
30 30 </div>
31 31
32 32 <script>
33 33 var url = "${h.url('formatted_users', format='json')}";
34 34 var data = ${c.data|n};
35 35 var myDataSource = new YAHOO.util.DataSource(data);
36 36 myDataSource.responseType = YAHOO.util.DataSource.TYPE_JSON;
37 37
38 38 myDataSource.responseSchema = {
39 39 resultsList: "records",
40 40 fields: [
41 41 {key: "gravatar"},
42 42 {key: "raw_username"},
43 43 {key: "username"},
44 44 {key: "firstname"},
45 45 {key: "lastname"},
46 46 {key: "last_login"},
47 47 {key: "last_login_raw"},
48 48 {key: "active"},
49 49 {key: "admin"},
50 50 {key: "ldap"},
51 51 {key: "action"},
52 52 ]
53 53 };
54 54 myDataSource.doBeforeCallback = function(req,raw,res,cb) {
55 55 // This is the filter function
56 56 var data = res.results || [],
57 57 filtered = [],
58 58 i,l;
59 59
60 60 if (req) {
61 61 req = req.toLowerCase();
62 62 for (i = 0; i<data.length; i++) {
63 63 var pos = data[i].raw_username.toLowerCase().indexOf(req)
64 64 if (pos != -1) {
65 65 filtered.push(data[i]);
66 66 }
67 67 }
68 68 res.results = filtered;
69 69 }
70 70 YUD.get('user_count').innerHTML = res.results.length;
71 71 return res;
72 72 }
73 73
74 74 // main table sorting
75 75 var myColumnDefs = [
76 76 {key:"gravatar",label:"",sortable:false,},
77 77 {key:"username",label:"${_('Username')}",sortable:true,
78 78 sortOptions: { sortFunction: usernamelinkSort }
79 79 },
80 80 {key:"firstname",label:"${_('Firstname')}",sortable:true,},
81 81 {key:"lastname",label:"${_('Lastname')}",sortable:true,},
82 82 {key:"last_login",label:"${_('Last login')}",sortable:true,
83 83 sortOptions: { sortFunction: lastLoginSort }},
84 84 {key:"active",label:"${_('Active')}",sortable:true,},
85 85 {key:"admin",label:"${_('Admin')}",sortable:true,},
86 86 {key:"ldap",label:"${_('LDAP')}",sortable:true,},
87 87 {key:"action",label:"${_('Action')}",sortable:false},
88 88 ];
89 89
90 90 var myDataTable = new YAHOO.widget.DataTable("users_list_wrap", myColumnDefs, myDataSource,{
91 91 sortedBy:{key:"username",dir:"asc"},
92 92 paginator: new YAHOO.widget.Paginator({
93 93 rowsPerPage: 15,
94 94 alwaysVisible: false,
95 95 template : "{PreviousPageLink} {FirstPageLink} {PageLinks} {LastPageLink} {NextPageLink}",
96 96 pageLinks: 5,
97 97 containerClass: 'pagination-wh',
98 98 currentPageClass: 'pager_curpage',
99 99 pageLinkClass: 'pager_link',
100 100 nextPageLinkLabel: '&gt;',
101 101 previousPageLinkLabel: '&lt;',
102 102 firstPageLinkLabel: '&lt;&lt;',
103 103 lastPageLinkLabel: '&gt;&gt;',
104 104 containers:['user-paginator']
105 105 }),
106 106
107 107 MSG_SORTASC:"${_('Click to sort ascending')}",
108 108 MSG_SORTDESC:"${_('Click to sort descending')}",
109 109 MSG_EMPTY:"${_('No records found.')}",
110 110 MSG_ERROR:"${_('Data error.')}",
111 111 MSG_LOADING:"${_('Loading...')}",
112 112 }
113 113 );
114 114 myDataTable.subscribe('postRenderEvent',function(oArgs) {
115 115
116 116 });
117 117
118 118 var filterTimeout = null;
119 119
120 120 updateFilter = function () {
121 121 // Reset timeout
122 122 filterTimeout = null;
123 123
124 124 // Reset sort
125 125 var state = myDataTable.getState();
126 126 state.sortedBy = {key:'username', dir:YAHOO.widget.DataTable.CLASS_ASC};
127 127
128 128 // Get filtered data
129 129 myDataSource.sendRequest(YUD.get('q_filter').value,{
130 130 success : myDataTable.onDataReturnInitializeTable,
131 131 failure : myDataTable.onDataReturnInitializeTable,
132 132 scope : myDataTable,
133 133 argument: state
134 134 });
135 135
136 136 };
137 YUE.on('q_filter','click',function(){
138 YUD.get('q_filter').value = '';
139 });
140 137
141 138 YUE.on('q_filter','keyup',function (e) {
142 139 clearTimeout(filterTimeout);
143 140 filterTimeout = setTimeout(updateFilter,600);
144 141 });
145 142 </script>
146 143
147 144 </%def>
@@ -1,76 +1,76 b''
1 1 ## -*- coding: utf-8 -*-
2 2 <%inherit file="/base/base.html"/>
3 3
4 4 <%def name="title()">
5 5 ${_('%s Bookmarks') % c.repo_name} &middot; ${c.rhodecode_name}
6 6 </%def>
7 7
8 8 <%def name="breadcrumbs_links()">
9 <input class="q_filter_box" id="q_filter_bookmarks" size="15" type="text" name="filter" value="${_('quick filter...')}"/>
9 <input class="q_filter_box" id="q_filter_bookmarks" size="15" type="text" name="filter" placeholder="${_('quick filter...')}" value=""/>
10 10 ${_('Bookmarks')}
11 11 </%def>
12 12
13 13 <%def name="page_nav()">
14 14 ${self.menu('repositories')}
15 15 </%def>
16 16
17 17 <%def name="main()">
18 18 ${self.context_bar('switch-to')}
19 19 <div class="box">
20 20 <!-- box / title -->
21 21 <div class="title">
22 22 ${self.breadcrumbs()}
23 23 </div>
24 24 <!-- end box / title -->
25 25 <div class="table">
26 26 <%include file='bookmarks_data.html'/>
27 27 </div>
28 28 </div>
29 29
30 30 <script type="text/javascript">
31 31
32 32 // main table sorting
33 33 var myColumnDefs = [
34 34 {key:"name",label:"${_('Name')}",sortable:true},
35 35 {key:"date",label:"${_('Date')}",sortable:true,
36 36 sortOptions: { sortFunction: dateSort }},
37 37 {key:"author",label:"${_('Author')}",sortable:true},
38 38 {key:"revision",label:"${_('Revision')}",sortable:true,
39 39 sortOptions: { sortFunction: revisionSort }},
40 40 ];
41 41
42 42 var myDataSource = new YAHOO.util.DataSource(YUD.get("bookmarks_data"));
43 43
44 44 myDataSource.responseType = YAHOO.util.DataSource.TYPE_HTMLTABLE;
45 45
46 46 myDataSource.responseSchema = {
47 47 fields: [
48 48 {key:"name"},
49 49 {key:"date"},
50 50 {key:"author"},
51 51 {key:"revision"},
52 52 ]
53 53 };
54 54
55 55 var myDataTable = new YAHOO.widget.DataTable("table_wrap", myColumnDefs, myDataSource,
56 56 {
57 57 sortedBy:{key:"name",dir:"asc"},
58 58 MSG_SORTASC:"${_('Click to sort ascending')}",
59 59 MSG_SORTDESC:"${_('Click to sort descending')}",
60 60 MSG_EMPTY:"${_('No records found.')}",
61 61 MSG_ERROR:"${_('Data error.')}",
62 62 MSG_LOADING:"${_('Loading...')}",
63 63 }
64 64 );
65 65 myDataTable.subscribe('postRenderEvent',function(oArgs) {
66 66 tooltip_activate();
67 67 var func = function(node){
68 68 return node.parentNode.parentNode.parentNode.parentNode.parentNode;
69 69 }
70 70 q_filter('q_filter_bookmarks',YUQ('div.table tr td .logbooks .bookbook a'),func);
71 71 });
72 72
73 73 </script>
74 74
75 75
76 76 </%def>
@@ -1,90 +1,90 b''
1 1 ## -*- coding: utf-8 -*-
2 2 <%inherit file="/base/base.html"/>
3 3
4 4 <%def name="title()">
5 5 ${_('%s Branches') % c.repo_name} &middot; ${c.rhodecode_name}
6 6 </%def>
7 7
8 8 <%def name="breadcrumbs_links()">
9 <input class="q_filter_box" id="q_filter_branches" size="15" type="text" name="filter" value="${_('quick filter...')}"/>
9 <input class="q_filter_box" id="q_filter_branches" size="15" type="text" name="filter" placeholder="${_('quick filter...')}" value=""/>
10 10 ${_('Branches')}
11 11 </%def>
12 12
13 13 <%def name="page_nav()">
14 14 ${self.menu('repositories')}
15 15 </%def>
16 16
17 17 <%def name="main()">
18 18 ${self.context_bar('switch-to')}
19 19 <div class="box">
20 20 <!-- box / title -->
21 21 <div class="title">
22 22 ${self.breadcrumbs()}
23 23 </div>
24 24 <!-- end box / title -->
25 25 %if c.repo_branches:
26 26 <div class="info_box" id="compare_branches" style="clear: both;padding: 10px 19px;text-align: right;"><a href="#" class="ui-btn small">${_('Compare branches')}</a></div>
27 27 %endif
28 28 <div class="table">
29 29 <%include file='branches_data.html'/>
30 30 </div>
31 31 </div>
32 32 <script type="text/javascript">
33 33 YUE.on('compare_branches','click',function(e){
34 34 YUE.preventDefault(e);
35 35 var org = YUQ('input[name=compare_org]:checked')[0];
36 36 var other = YUQ('input[name=compare_other]:checked')[0];
37 37
38 38 if(org && other){
39 39 var compare_url = "${h.url('compare_url',repo_name=c.repo_name,org_ref_type='branch',org_ref='__ORG__',other_ref_type='branch',other_ref='__OTHER__')}";
40 40 var u = compare_url.replace('__ORG__',org.value)
41 41 .replace('__OTHER__',other.value);
42 42 window.location=u;
43 43 }
44 44 });
45 45 // main table sorting
46 46 var myColumnDefs = [
47 47 {key:"name",label:"${_('Name')}",sortable:true},
48 48 {key:"date",label:"${_('Date')}",sortable:true,
49 49 sortOptions: { sortFunction: dateSort }},
50 50 {key:"author",label:"${_('Author')}",sortable:true},
51 51 {key:"revision",label:"${_('Revision')}",sortable:true,
52 52 sortOptions: { sortFunction: revisionSort }},
53 53 {key:"compare",label:"${_('Compare')}",sortable:false,},
54 54 ];
55 55
56 56 var myDataSource = new YAHOO.util.DataSource(YUD.get("branches_data"));
57 57
58 58 myDataSource.responseType = YAHOO.util.DataSource.TYPE_HTMLTABLE;
59 59
60 60 myDataSource.responseSchema = {
61 61 fields: [
62 62 {key:"name"},
63 63 {key:"date"},
64 64 {key:"author"},
65 65 {key:"revision"},
66 66 {key:"compare"},
67 67 ]
68 68 };
69 69
70 70 var myDataTable = new YAHOO.widget.DataTable("table_wrap", myColumnDefs, myDataSource,
71 71 {
72 72 sortedBy:{key:"name",dir:"asc"},
73 73 MSG_SORTASC:"${_('Click to sort ascending')}",
74 74 MSG_SORTDESC:"${_('Click to sort descending')}",
75 75 MSG_EMPTY:"${_('No records found.')}",
76 76 MSG_ERROR:"${_('Data error.')}",
77 77 MSG_LOADING:"${_('Loading...')}",
78 78 }
79 79 );
80 80 myDataTable.subscribe('postRenderEvent',function(oArgs) {
81 81 tooltip_activate();
82 82 var func = function(node){
83 83 return node.parentNode.parentNode.parentNode.parentNode.parentNode;
84 84 }
85 85 q_filter('q_filter_branches',YUQ('div.table tr td .logtags .branchtag a'),func);
86 86 });
87 87
88 88 </script>
89 89
90 90 </%def>
@@ -1,340 +1,339 b''
1 1 <%page args="parent" />
2 2 <div class="box">
3 3 <!-- box / title -->
4 4 <div class="title">
5 5 <h5>
6 <input class="q_filter_box" id="q_filter" size="15" type="text" name="filter" value="${_('quick filter...')}"/> ${parent.breadcrumbs()} <span id="repo_count">0</span> ${_('repositories')}
6 <input class="q_filter_box" id="q_filter" size="15" type="text" name="filter" placeholder="${_('quick filter...')}" value=""/> ${parent.breadcrumbs()} <span id="repo_count">0</span> ${_('repositories')}
7 7 </h5>
8 8 %if c.rhodecode_user.username != 'default':
9 9 <ul class="links">
10 10 %if h.HasPermissionAny('hg.admin','hg.create.repository')() or h.HasReposGroupPermissionAny('group.write', 'group.admin')(c.group.group_name if c.group else None):
11 11 <li>
12 12 %if c.group:
13 13 <span>${h.link_to(_('Add repository'),h.url('new_repo',parent_group=c.group.group_id))}</span>
14 14 %if h.HasPermissionAny('hg.admin')() or h.HasReposGroupPermissionAny('group.admin')(c.group.group_name):
15 15 <span>${h.link_to(_(u'Add group'),h.url('new_repos_group', parent_group=c.group.group_id))}</span>
16 16 %endif
17 17 %else:
18 18 <span>${h.link_to(_('Add repository'),h.url('new_repo'))}</span>
19 19 %if h.HasPermissionAny('hg.admin')():
20 20 <span>${h.link_to(_(u'Add group'),h.url('new_repos_group'))}</span>
21 21 %endif
22 22 %endif
23 23 </li>
24 24 %endif
25 25 %if c.group and h.HasReposGroupPermissionAny('group.admin')(c.group.group_name):
26 26 <li>
27 27 <span>${h.link_to(_('Edit group'),h.url('edit_repos_group',group_name=c.group.group_name), title=_('You have admin right to this group, and can edit it'))}</span>
28 28 </li>
29 29 %endif
30 30 </ul>
31 31 %endif
32 32 </div>
33 33 <!-- end box / title -->
34 34 <div class="table">
35 35 % if c.groups:
36 36 <div id='groups_list_wrap' class="yui-skin-sam">
37 37 <table id="groups_list">
38 38 <thead>
39 39 <tr>
40 40 <th class="left"><a href="#">${_('Group name')}</a></th>
41 41 <th class="left"><a href="#">${_('Description')}</a></th>
42 42 ##<th class="left"><a href="#">${_('Number of repositories')}</a></th>
43 43 </tr>
44 44 </thead>
45 45
46 46 ## REPO GROUPS
47 47 % for gr in c.groups:
48 48 <tr>
49 49 <td>
50 50 <div style="white-space: nowrap">
51 51 <img class="icon" alt="${_('Repository group')}" src="${h.url('/images/icons/database_link.png')}"/>
52 52 ${h.link_to(gr.name,url('repos_group_home',group_name=gr.group_name))}
53 53 </div>
54 54 </td>
55 55 %if c.visual.stylify_metatags:
56 56 <td>${h.urlify_text(h.desc_stylize(gr.group_description))}</td>
57 57 %else:
58 58 <td>${gr.group_description}</td>
59 59 %endif
60 60 ## this is commented out since for multi nested repos can be HEAVY!
61 61 ## in number of executed queries during traversing uncomment at will
62 62 ##<td><b>${gr.repositories_recursive_count}</b></td>
63 63 </tr>
64 64 % endfor
65 65 </table>
66 66 </div>
67 67 <div id="group-user-paginator" style="padding: 0px 0px 0px 0px"></div>
68 68 <div style="height: 20px"></div>
69 69 % endif
70 70 <div id="welcome" style="display:none;text-align:center">
71 71 <h1><a href="${h.url('home')}">${c.rhodecode_name} ${c.rhodecode_version}</a></h1>
72 72 </div>
73 73 <%cnt=0%>
74 74 <%namespace name="dt" file="/data_table/_dt_elements.html"/>
75 75 % if not c.visual.lightweight_dashboard:
76 76 ## old full detailed version
77 77 <div id='repos_list_wrap' class="yui-skin-sam">
78 78 <table id="repos_list">
79 79 <thead>
80 80 <tr>
81 81 <th class="left"></th>
82 82 <th class="left">${_('Name')}</th>
83 83 <th class="left">${_('Description')}</th>
84 84 <th class="left">${_('Last change')}</th>
85 85 <th class="left">${_('Tip')}</th>
86 86 <th class="left">${_('Owner')}</th>
87 87 <th class="left">${_('Atom')}</th>
88 88 </tr>
89 89 </thead>
90 90 <tbody>
91 91 %for cnt,repo in enumerate(c.repos_list):
92 92 <tr class="parity${(cnt+1)%2}">
93 93 ##QUICK MENU
94 94 <td class="quick_repo_menu">
95 95 ${dt.quick_menu(repo['name'])}
96 96 </td>
97 97 ##REPO NAME AND ICONS
98 98 <td class="reponame">
99 99 ${dt.repo_name(repo['name'],repo['dbrepo']['repo_type'],repo['dbrepo']['private'],h.AttributeDict(repo['dbrepo_fork']),pageargs.get('short_repo_names'))}
100 100 </td>
101 101 ##DESCRIPTION
102 102 <td><span class="tooltip" title="${h.tooltip(repo['description'])}">
103 103 %if c.visual.stylify_metatags:
104 104 ${h.urlify_text(h.desc_stylize(h.truncate(repo['description'],60)))}</span>
105 105 %else:
106 106 ${h.truncate(repo['description'],60)}</span>
107 107 %endif
108 108 </td>
109 109 ##LAST CHANGE DATE
110 110 <td>
111 111 ${dt.last_change(repo['last_change'])}
112 112 </td>
113 113 ##LAST REVISION
114 114 <td>
115 115 ${dt.revision(repo['name'],repo['rev'],repo['tip'],repo['author'],repo['last_msg'])}
116 116 </td>
117 117 ##
118 118 <td title="${repo['contact']}">${h.person(repo['contact'])}</td>
119 119 <td>
120 120 ${dt.atom(repo['name'])}
121 121 </td>
122 122 </tr>
123 123 %endfor
124 124 </tbody>
125 125 </table>
126 126 </div>
127 127 % else:
128 128 ## lightweight version
129 129 <div class="yui-skin-sam" id="repos_list_wrap"></div>
130 130 <div id="user-paginator" style="padding: 0px 0px 0px 0px"></div>
131 131 % endif
132 132 </div>
133 133 </div>
134 134 % if not c.visual.lightweight_dashboard:
135 135 <script>
136 136 YUD.get('repo_count').innerHTML = ${cnt+1 if cnt else 0};
137 137
138 138 // groups table sorting
139 139 var myColumnDefs = [
140 140 {key:"name",label:"${_('Group name')}",sortable:true,
141 141 sortOptions: { sortFunction: groupNameSort }},
142 142 {key:"desc",label:"${_('Description')}",sortable:true},
143 143 ];
144 144
145 145 var myDataSource = new YAHOO.util.DataSource(YUD.get("groups_list"));
146 146
147 147 myDataSource.responseType = YAHOO.util.DataSource.TYPE_HTMLTABLE;
148 148 myDataSource.responseSchema = {
149 149 fields: [
150 150 {key:"name"},
151 151 {key:"desc"},
152 152 ]
153 153 };
154 154
155 155 var myDataTable = new YAHOO.widget.DataTable("groups_list_wrap", myColumnDefs, myDataSource,{
156 156 sortedBy:{key:"name",dir:"asc"},
157 157 paginator: new YAHOO.widget.Paginator({
158 158 rowsPerPage: 50,
159 159 alwaysVisible: false,
160 160 template : "{PreviousPageLink} {FirstPageLink} {PageLinks} {LastPageLink} {NextPageLink}",
161 161 pageLinks: 5,
162 162 containerClass: 'pagination-wh',
163 163 currentPageClass: 'pager_curpage',
164 164 pageLinkClass: 'pager_link',
165 165 nextPageLinkLabel: '&gt;',
166 166 previousPageLinkLabel: '&lt;',
167 167 firstPageLinkLabel: '&lt;&lt;',
168 168 lastPageLinkLabel: '&gt;&gt;',
169 169 containers:['group-user-paginator']
170 170 }),
171 171 MSG_SORTASC:"${_('Click to sort ascending')}",
172 172 MSG_SORTDESC:"${_('Click to sort descending')}"
173 173 });
174 174
175 175 // main table sorting
176 176 var myColumnDefs = [
177 177 {key:"menu",label:"",sortable:false,className:"quick_repo_menu hidden"},
178 178 {key:"name",label:"${_('Name')}",sortable:true,
179 179 sortOptions: { sortFunction: nameSort }},
180 180 {key:"desc",label:"${_('Description')}",sortable:true},
181 181 {key:"last_change",label:"${_('Last Change')}",sortable:true,
182 182 sortOptions: { sortFunction: ageSort }},
183 183 {key:"tip",label:"${_('Tip')}",sortable:true,
184 184 sortOptions: { sortFunction: revisionSort }},
185 185 {key:"owner",label:"${_('Owner')}",sortable:true},
186 186 {key:"atom",label:"",sortable:false},
187 187 ];
188 188
189 189 var myDataSource = new YAHOO.util.DataSource(YUD.get("repos_list"));
190 190
191 191 myDataSource.responseType = YAHOO.util.DataSource.TYPE_HTMLTABLE;
192 192
193 193 myDataSource.responseSchema = {
194 194 fields: [
195 195 {key:"menu"},
196 196 //{key:"raw_name"},
197 197 {key:"name"},
198 198 {key:"desc"},
199 199 {key:"last_change"},
200 200 {key:"tip"},
201 201 {key:"owner"},
202 202 {key:"atom"},
203 203 ]
204 204 };
205 205
206 206 var myDataTable = new YAHOO.widget.DataTable("repos_list_wrap", myColumnDefs, myDataSource,
207 207 {
208 208 sortedBy:{key:"name",dir:"asc"},
209 209 MSG_SORTASC:"${_('Click to sort ascending')}",
210 210 MSG_SORTDESC:"${_('Click to sort descending')}",
211 211 MSG_EMPTY:"${_('No records found.')}",
212 212 MSG_ERROR:"${_('Data error.')}",
213 213 MSG_LOADING:"${_('Loading...')}",
214 214 }
215 215 );
216 216 myDataTable.subscribe('postRenderEvent',function(oArgs) {
217 217 tooltip_activate();
218 218 quick_repo_menu();
219 219 var func = function(node){
220 220 return node.parentNode.parentNode.parentNode.parentNode;
221 221 }
222 222 q_filter('q_filter',YUQ('div.table tr td a.repo_name'),func);
223 223 });
224 224
225 225 </script>
226 226 % else:
227 227 <script>
228 228 var data = ${c.data|n};
229 229 var myDataSource = new YAHOO.util.DataSource(data);
230 230 myDataSource.responseType = YAHOO.util.DataSource.TYPE_JSON;
231 231
232 232 myDataSource.responseSchema = {
233 233 resultsList: "records",
234 234 fields: [
235 235 {key:"menu"},
236 236 {key:"raw_name"},
237 237 {key:"name"},
238 238 {key:"desc"},
239 239 {key:"last_change"},
240 240 {key:"last_changeset"},
241 241 {key:"owner"},
242 242 {key:"atom"},
243 243 ]
244 244 };
245 245 myDataSource.doBeforeCallback = function(req,raw,res,cb) {
246 246 // This is the filter function
247 247 var data = res.results || [],
248 248 filtered = [],
249 249 i,l;
250 250
251 251 if (req) {
252 252 req = req.toLowerCase();
253 253 for (i = 0; i<data.length; i++) {
254 254 var pos = data[i].raw_name.toLowerCase().indexOf(req)
255 255 if (pos != -1) {
256 256 filtered.push(data[i]);
257 257 }
258 258 }
259 259 res.results = filtered;
260 260 }
261 261 YUD.get('repo_count').innerHTML = res.results.length;
262 262 return res;
263 263 }
264 264
265 265 // main table sorting
266 266 var myColumnDefs = [
267 267 {key:"menu",label:"",sortable:false,className:"quick_repo_menu hidden"},
268 268 {key:"name",label:"${_('Name')}",sortable:true,
269 269 sortOptions: { sortFunction: nameSort }},
270 270 {key:"desc",label:"${_('Description')}",sortable:true},
271 271 {key:"last_change",label:"${_('Last Change')}",sortable:true,
272 272 sortOptions: { sortFunction: ageSort }},
273 273 {key:"last_changeset",label:"${_('Tip')}",sortable:true,
274 274 sortOptions: { sortFunction: revisionSort }},
275 275 {key:"owner",label:"${_('Owner')}",sortable:true},
276 276 {key:"atom",label:"",sortable:false},
277 277 ];
278 278
279 279 var myDataTable = new YAHOO.widget.DataTable("repos_list_wrap", myColumnDefs, myDataSource,{
280 280 sortedBy:{key:"name",dir:"asc"},
281 281 paginator: new YAHOO.widget.Paginator({
282 282 rowsPerPage: ${c.visual.lightweight_dashboard_items},
283 283 alwaysVisible: false,
284 284 template : "{PreviousPageLink} {FirstPageLink} {PageLinks} {LastPageLink} {NextPageLink}",
285 285 pageLinks: 5,
286 286 containerClass: 'pagination-wh',
287 287 currentPageClass: 'pager_curpage',
288 288 pageLinkClass: 'pager_link',
289 289 nextPageLinkLabel: '&gt;',
290 290 previousPageLinkLabel: '&lt;',
291 291 firstPageLinkLabel: '&lt;&lt;',
292 292 lastPageLinkLabel: '&gt;&gt;',
293 293 containers:['user-paginator']
294 294 }),
295 295
296 296 MSG_SORTASC:"${_('Click to sort ascending')}",
297 297 MSG_SORTDESC:"${_('Click to sort descending')}",
298 298 MSG_EMPTY:"${_('No repositories found.')}",
299 299 MSG_ERROR:"${_('Data error.')}",
300 300 MSG_LOADING:"${_('Loading...')}",
301 301 }
302 302 );
303 303 myDataTable.subscribe('postRenderEvent',function(oArgs) {
304 304 tooltip_activate();
305 305 quick_repo_menu();
306 306 });
307 307
308 308 var filterTimeout = null;
309 309
310 310 updateFilter = function () {
311 311 // Reset timeout
312 312 filterTimeout = null;
313 313
314 314 // Reset sort
315 315 var state = myDataTable.getState();
316 316 state.sortedBy = {key:'name', dir:YAHOO.widget.DataTable.CLASS_ASC};
317 317
318 318 // Get filtered data
319 319 myDataSource.sendRequest(YUD.get('q_filter').value,{
320 320 success : myDataTable.onDataReturnInitializeTable,
321 321 failure : myDataTable.onDataReturnInitializeTable,
322 322 scope : myDataTable,
323 323 argument: state
324 324 });
325 325
326 326 };
327 327 YUE.on('q_filter','click',function(){
328 328 if(!YUD.hasClass('q_filter', 'loaded')){
329 YUD.get('q_filter').value = '';
330 329 //TODO: load here full list later to do search within groups
331 330 YUD.addClass('q_filter', 'loaded');
332 331 }
333 332 });
334 333
335 334 YUE.on('q_filter','keyup',function (e) {
336 335 clearTimeout(filterTimeout);
337 336 filterTimeout = setTimeout(updateFilter,600);
338 337 });
339 338 </script>
340 339 % endif
@@ -1,367 +1,365 b''
1 1 ## -*- coding: utf-8 -*-
2 2 <%inherit file="/base/base.html"/>
3 3 <%def name="title()">
4 4 ${_('Journal')} &middot; ${c.rhodecode_name}
5 5 </%def>
6 6 <%def name="breadcrumbs()">
7 7 <h5>
8 8 <form id="filter_form">
9 9 <input class="q_filter_box ${'' if c.search_term else 'initial'}" id="j_filter" size="15" type="text" name="filter" value="${c.search_term or _('quick filter...')}"/>
10 10 <span class="tooltip" title="${h.tooltip(h.journal_filter_help())}">?</span>
11 11 <input type='submit' value="${_('filter')}" class="ui-btn" style="padding:0px 2px 0px 2px;margin:0px"/>
12 12 ${_('journal')} - ${ungettext('%s entry', '%s entries', c.journal_pager.item_count) % (c.journal_pager.item_count)}
13 13 </form>
14 14 ${h.end_form()}
15 15 </h5>
16 16 </%def>
17 17 <%def name="page_nav()">
18 18 ${self.menu('journal')}
19 19 </%def>
20 20 <%def name="head_extra()">
21 21 <link href="${h.url('journal_atom', api_key=c.rhodecode_user.api_key)}" rel="alternate" title="${_('ATOM journal feed')}" type="application/atom+xml" />
22 22 <link href="${h.url('journal_rss', api_key=c.rhodecode_user.api_key)}" rel="alternate" title="${_('RSS journal feed')}" type="application/rss+xml" />
23 23 </%def>
24 24 <%def name="main()">
25 25
26 26 <div class="box box-left">
27 27 <!-- box / title -->
28 28 <div class="title">
29 29 ${self.breadcrumbs()}
30 30 <ul class="links">
31 31 <li>
32 32 <span><a id="refresh" href="${h.url('journal')}"><img class="icon" title="${_('Refresh')}" alt="${_('Refresh')}" src="${h.url('/images/icons/arrow_refresh.png')}"/></a></span>
33 33 </li>
34 34 <li>
35 35 <span><a href="${h.url('journal_atom', api_key=c.rhodecode_user.api_key)}"><img class="icon" title="${_('ATOM feed')}" alt="${_('ATOM feed')}" src="${h.url('/images/icons/rss_16.png')}"/></a></span>
36 36 </li>
37 37 </ul>
38 38 </div>
39 39 <div id="journal">${c.journal_data}</div>
40 40 </div>
41 41 <div class="box box-right">
42 42 <!-- box / title -->
43 43
44 44 <div class="title">
45 45 <h5>
46 <input class="q_filter_box" id="q_filter" size="15" type="text" name="filter" value="${_('quick filter...')}" style="display: none"/>
47 <input class="q_filter_box" id="q_filter_watched" size="15" type="text" name="filter" value="${_('quick filter...')}" style="display: none"/>
46 <input class="q_filter_box" id="q_filter" size="15" type="text" name="filter" placeholder="${_('quick filter...')}" value="" style="display: none"/>
47 <input class="q_filter_box" id="q_filter_watched" size="15" type="text" name="filter" placeholder="${_('quick filter...')}" value="" style="display: none"/>
48 48 </h5>
49 49 <ul class="links" style="color:#DADADA">
50 50 <li>
51 51 <span><a id="show_watched" class="link-white current" href="#watched">${_('Watched')}</a> </span>
52 52 </li>
53 53 <li>
54 54 <span><a id="show_my" class="link-white" href="#my">${_('My repos')}</a> </span>
55 55 </li>
56 56 </ul>
57 57 </div>
58 58
59 59 <!-- end box / title -->
60 60 <div id="my_container" style="display:none">
61 61 <div class="table yui-skin-sam" id="repos_list_wrap"></div>
62 62 <div id="user-paginator" style="padding: 0px 0px 0px 20px"></div>
63 63 </div>
64 64
65 65 <div id="watched_container">
66 66 <div class="table yui-skin-sam" id="watched_repos_list_wrap"></div>
67 67 <div id="watched-user-paginator" style="padding: 0px 0px 0px 20px"></div>
68 68 </div>
69 69 </div>
70 70
71 71 <script type="text/javascript">
72 72
73 73 YUE.on('j_filter','click',function(){
74 74 var jfilter = YUD.get('j_filter');
75 75 if(YUD.hasClass(jfilter, 'initial')){
76 76 jfilter.value = '';
77 77 }
78 78 });
79 79 var fix_j_filter_width = function(len){
80 80 YUD.setStyle(YUD.get('j_filter'),'width',Math.max(80, len*6.50)+'px');
81 81 }
82 82 YUE.on('j_filter','keyup',function(){
83 83 fix_j_filter_width(YUD.get('j_filter').value.length);
84 84 });
85 85 YUE.on('filter_form','submit',function(e){
86 86 YUE.preventDefault(e)
87 87 var val = YUD.get('j_filter').value;
88 88 window.location = "${url.current(filter='__FILTER__')}".replace('__FILTER__',val);
89 89 });
90 90 fix_j_filter_width(YUD.get('j_filter').value.length);
91 91
92 92 YUE.on('refresh','click',function(e){
93 93 ypjax("${h.url.current(filter=c.search_term)}","journal",function(){
94 94 show_more_event();
95 95 tooltip_activate();
96 96 show_changeset_tooltip();
97 97 });
98 98 YUE.preventDefault(e);
99 99 });
100 100
101 101 var show_my = function(e){
102 102 YUD.setStyle('watched_container','display','none');
103 103 YUD.setStyle('my_container','display','');
104 104 YUD.setStyle('q_filter','display','');
105 105 YUD.setStyle('q_filter_watched','display','none');
106 106
107 107 YUD.addClass('show_my', 'current');
108 108 YUD.removeClass('show_watched','current');
109 109
110 110 if(!YUD.hasClass('show_my', 'loaded')){
111 111 table_renderer(${c.data |n});
112 112 YUD.addClass('show_my', 'loaded');
113 113 }
114 114 }
115 115 YUE.on('show_my','click',function(e){
116 116 show_my(e);
117 117 })
118 118 var show_watched = function(e){
119 119 YUD.setStyle('my_container','display','none');
120 120 YUD.setStyle('watched_container','display','');
121 121 YUD.setStyle('q_filter_watched','display','');
122 122 YUD.setStyle('q_filter','display','none');
123 123
124 124 YUD.addClass('show_watched', 'current');
125 125 YUD.removeClass('show_my','current');
126 126 if(!YUD.hasClass('show_watched', 'loaded')){
127 127 watched_renderer(${c.watched_data |n});
128 128 YUD.addClass('show_watched', 'loaded');
129 129 }
130 130
131 131 return
132 132 var nodes = YUQ('#watched_container .watched_repo a');
133 133 var target = 'q_filter';
134 134 var func = function(node){
135 135 return node.parentNode.parentNode;
136 136 }
137 137 q_filter(target,nodes,func);
138 138 }
139 139 YUE.on('show_watched','click',function(e){
140 140 show_watched(e);
141 141 })
142 142 //init watched
143 143 show_watched();
144 144
145 145 var tabs = {
146 146 'watched': show_watched,
147 147 'my': show_my,
148 148 }
149 149 var url = location.href.split('#');
150 150 if (url[1]) {
151 151 //We have a hash
152 152 var tabHash = url[1];
153 153 var func = tabs[tabHash]
154 154 if (func){
155 155 func();
156 156 }
157 157 }
158 158 function watched_renderer(data){
159 159 var myDataSource = new YAHOO.util.DataSource(data);
160 160 myDataSource.responseType = YAHOO.util.DataSource.TYPE_JSON;
161 161
162 162 myDataSource.responseSchema = {
163 163 resultsList: "records",
164 164 fields: [
165 165 {key:"menu"},
166 166 {key:"raw_name"},
167 167 {key:"name"},
168 168 {key:"last_changeset"},
169 169 {key:"action"},
170 170 ]
171 171 };
172 172 myDataSource.doBeforeCallback = function(req,raw,res,cb) {
173 173 // This is the filter function
174 174 var data = res.results || [],
175 175 filtered = [],
176 176 i,l;
177 177
178 178 if (req) {
179 179 req = req.toLowerCase();
180 180 for (i = 0; i<data.length; i++) {
181 181 var pos = data[i].raw_name.toLowerCase().indexOf(req)
182 182 if (pos != -1) {
183 183 filtered.push(data[i]);
184 184 }
185 185 }
186 186 res.results = filtered;
187 187 }
188 188 return res;
189 189 }
190 190 // main table sorting
191 191 var myColumnDefs = [
192 192 {key:"menu",label:"",sortable:false,className:"quick_repo_menu hidden"},
193 193 {key:"name",label:"${_('Name')}",sortable:true,
194 194 sortOptions: { sortFunction: nameSort }},
195 195 {key:"last_changeset",label:"${_('Tip')}",sortable:true,
196 196 sortOptions: { sortFunction: revisionSort }},
197 197 {key:"action",label:"${_('Action')}",sortable:false},
198 198 ];
199 199
200 200 var myDataTable = new YAHOO.widget.DataTable("watched_repos_list_wrap", myColumnDefs, myDataSource,{
201 201 sortedBy:{key:"name",dir:"asc"},
202 202 paginator: new YAHOO.widget.Paginator({
203 203 rowsPerPage: 25,
204 204 alwaysVisible: false,
205 205 template : "{PreviousPageLink} {FirstPageLink} {PageLinks} {LastPageLink} {NextPageLink}",
206 206 pageLinks: 5,
207 207 containerClass: 'pagination-wh',
208 208 currentPageClass: 'pager_curpage',
209 209 pageLinkClass: 'pager_link',
210 210 nextPageLinkLabel: '&gt;',
211 211 previousPageLinkLabel: '&lt;',
212 212 firstPageLinkLabel: '&lt;&lt;',
213 213 lastPageLinkLabel: '&gt;&gt;',
214 214 containers:['watched-user-paginator']
215 215 }),
216 216
217 217 MSG_SORTASC:"${_('Click to sort ascending')}",
218 218 MSG_SORTDESC:"${_('Click to sort descending')}",
219 219 MSG_EMPTY:"${_('No records found.')}",
220 220 MSG_ERROR:"${_('Data error.')}",
221 221 MSG_LOADING:"${_('Loading...')}",
222 222 }
223 223 );
224 224 myDataTable.subscribe('postRenderEvent',function(oArgs) {
225 225 tooltip_activate();
226 226 quick_repo_menu();
227 227 });
228 228
229 229 var filterTimeout = null;
230 230
231 231 updateFilter = function () {
232 232 // Reset timeout
233 233 filterTimeout = null;
234 234
235 235 // Reset sort
236 236 var state = myDataTable.getState();
237 237 state.sortedBy = {key:'name', dir:YAHOO.widget.DataTable.CLASS_ASC};
238 238
239 239 // Get filtered data
240 240 myDataSource.sendRequest(YUD.get('q_filter_watched').value,{
241 241 success : myDataTable.onDataReturnInitializeTable,
242 242 failure : myDataTable.onDataReturnInitializeTable,
243 243 scope : myDataTable,
244 244 argument: state
245 245 });
246 246
247 247 };
248 248 YUE.on('q_filter_watched','click',function(){
249 249 if(!YUD.hasClass('q_filter_watched', 'loaded')){
250 YUD.get('q_filter_watched').value = '';
251 250 //TODO: load here full list later to do search within groups
252 251 YUD.addClass('q_filter_watched', 'loaded');
253 252 }
254 253 });
255 254
256 255 YUE.on('q_filter_watched','keyup',function (e) {
257 256 clearTimeout(filterTimeout);
258 257 filterTimeout = setTimeout(updateFilter,600);
259 258 });
260 259 }
261 260
262 261 function table_renderer(data){
263 262 var myDataSource = new YAHOO.util.DataSource(data);
264 263 myDataSource.responseType = YAHOO.util.DataSource.TYPE_JSON;
265 264
266 265 myDataSource.responseSchema = {
267 266 resultsList: "records",
268 267 fields: [
269 268 {key:"menu"},
270 269 {key:"raw_name"},
271 270 {key:"name"},
272 271 {key:"last_changeset"},
273 272 {key:"action"},
274 273 ]
275 274 };
276 275 myDataSource.doBeforeCallback = function(req,raw,res,cb) {
277 276 // This is the filter function
278 277 var data = res.results || [],
279 278 filtered = [],
280 279 i,l;
281 280
282 281 if (req) {
283 282 req = req.toLowerCase();
284 283 for (i = 0; i<data.length; i++) {
285 284 var pos = data[i].raw_name.toLowerCase().indexOf(req)
286 285 if (pos != -1) {
287 286 filtered.push(data[i]);
288 287 }
289 288 }
290 289 res.results = filtered;
291 290 }
292 291 return res;
293 292 }
294 293 // main table sorting
295 294 var myColumnDefs = [
296 295 {key:"menu",label:"",sortable:false,className:"quick_repo_menu hidden"},
297 296 {key:"name",label:"${_('Name')}",sortable:true,
298 297 sortOptions: { sortFunction: nameSort }},
299 298 {key:"last_changeset",label:"${_('Tip')}",sortable:true,
300 299 sortOptions: { sortFunction: revisionSort }},
301 300 {key:"action",label:"${_('Action')}",sortable:false},
302 301 ];
303 302
304 303 var myDataTable = new YAHOO.widget.DataTable("repos_list_wrap", myColumnDefs, myDataSource,{
305 304 sortedBy:{key:"name",dir:"asc"},
306 305 paginator: new YAHOO.widget.Paginator({
307 306 rowsPerPage: 25,
308 307 alwaysVisible: false,
309 308 template : "{PreviousPageLink} {FirstPageLink} {PageLinks} {LastPageLink} {NextPageLink}",
310 309 pageLinks: 5,
311 310 containerClass: 'pagination-wh',
312 311 currentPageClass: 'pager_curpage',
313 312 pageLinkClass: 'pager_link',
314 313 nextPageLinkLabel: '&gt;',
315 314 previousPageLinkLabel: '&lt;',
316 315 firstPageLinkLabel: '&lt;&lt;',
317 316 lastPageLinkLabel: '&gt;&gt;',
318 317 containers:['user-paginator']
319 318 }),
320 319
321 320 MSG_SORTASC:"${_('Click to sort ascending')}",
322 321 MSG_SORTDESC:"${_('Click to sort descending')}",
323 322 MSG_EMPTY:"${_('No records found.')}",
324 323 MSG_ERROR:"${_('Data error.')}",
325 324 MSG_LOADING:"${_('Loading...')}",
326 325 }
327 326 );
328 327 myDataTable.subscribe('postRenderEvent',function(oArgs) {
329 328 tooltip_activate();
330 329 quick_repo_menu();
331 330 });
332 331
333 332 var filterTimeout = null;
334 333
335 334 updateFilter = function () {
336 335 // Reset timeout
337 336 filterTimeout = null;
338 337
339 338 // Reset sort
340 339 var state = myDataTable.getState();
341 340 state.sortedBy = {key:'name', dir:YAHOO.widget.DataTable.CLASS_ASC};
342 341
343 342 // Get filtered data
344 343 myDataSource.sendRequest(YUD.get('q_filter').value,{
345 344 success : myDataTable.onDataReturnInitializeTable,
346 345 failure : myDataTable.onDataReturnInitializeTable,
347 346 scope : myDataTable,
348 347 argument: state
349 348 });
350 349
351 350 };
352 351 YUE.on('q_filter','click',function(){
353 352 if(!YUD.hasClass('q_filter', 'loaded')){
354 YUD.get('q_filter').value = '';
355 353 //TODO: load here full list later to do search within groups
356 354 YUD.addClass('q_filter', 'loaded');
357 355 }
358 356 });
359 357
360 358 YUE.on('q_filter','keyup',function (e) {
361 359 clearTimeout(filterTimeout);
362 360 filterTimeout = setTimeout(updateFilter,600);
363 361 });
364 362 }
365 363
366 364 </script>
367 365 </%def>
@@ -1,16 +1,16 b''
1 1 ## -*- coding: utf-8 -*-
2 2
3 3 <li class="qfilter_rs">
4 <input type="text" style="border:0;width:100%" value="${_('quick filter...')}" name="filter" id="q_filter_rs" />
4 <input type="text" style="border:0;width:100%" placeholder="${_('quick filter...')}" value="" name="filter" id="q_filter_rs" />
5 5 </li>
6 6
7 7 %for repo in c.repos_list:
8 8 <li>
9 9 %if repo['dbrepo']['private'] and c.visual.show_private_icon:
10 10 <img src="${h.url('/images/icons/lock.png')}" alt="${_('Private repository')}" class="repo_switcher_type"/>
11 11 %elif not repo['dbrepo']['private'] and c.visual.show_public_icon:
12 12 <img src="${h.url('/images/icons/lock_open.png')}" alt="${_('Public repository')}" class="repo_switcher_type" />
13 13 %endif
14 14 ${h.link_to(repo['name'],h.url('summary_home',repo_name=repo['name']),class_="repo_name thin %s" % repo['dbrepo']['repo_type'])}
15 15 </li>
16 16 %endfor
@@ -1,90 +1,90 b''
1 1 ## -*- coding: utf-8 -*-
2 2 <%inherit file="/base/base.html"/>
3 3
4 4 <%def name="title()">
5 5 ${_('%s Tags') % c.repo_name} &middot; ${c.rhodecode_name}
6 6 </%def>
7 7
8 8 <%def name="breadcrumbs_links()">
9 <input class="q_filter_box" id="q_filter_tags" size="15" type="text" name="filter" value="${_('quick filter...')}"/>
9 <input class="q_filter_box" id="q_filter_tags" size="15" type="text" name="filter" placeholder="${_('quick filter...')}" value=""/>
10 10 ${_('Tags')}
11 11 </%def>
12 12
13 13 <%def name="page_nav()">
14 14 ${self.menu('repositories')}
15 15 </%def>
16 16
17 17 <%def name="main()">
18 18 ${self.context_bar('switch-to')}
19 19 <div class="box">
20 20 <!-- box / title -->
21 21 <div class="title">
22 22 ${self.breadcrumbs()}
23 23 </div>
24 24 <!-- end box / title -->
25 25 %if c.repo_tags:
26 26 <div class="info_box" id="compare_tags" style="clear: both;padding: 10px 19px;text-align: right;"><a href="#" class="ui-btn small">${_('Compare tags')}</a></div>
27 27 %endif
28 28 <div class="table">
29 29 <%include file='tags_data.html'/>
30 30 </div>
31 31 </div>
32 32 <script type="text/javascript">
33 33 YUE.on('compare_tags','click',function(e){
34 34 YUE.preventDefault(e);
35 35 var org = YUQ('input[name=compare_org]:checked')[0];
36 36 var other = YUQ('input[name=compare_other]:checked')[0];
37 37
38 38 if(org && other){
39 39 var compare_url = "${h.url('compare_url',repo_name=c.repo_name,org_ref_type='tag',org_ref='__ORG__',other_ref_type='tag',other_ref='__OTHER__')}";
40 40 var u = compare_url.replace('__ORG__',org.value)
41 41 .replace('__OTHER__',other.value);
42 42 window.location=u;
43 43 }
44 44 });
45 45
46 46 // main table sorting
47 47 var myColumnDefs = [
48 48 {key:"name",label:"${_('Name')}",sortable:true},
49 49 {key:"date",label:"${_('Date')}",sortable:true,
50 50 sortOptions: { sortFunction: dateSort }},
51 51 {key:"author",label:"${_('Author')}",sortable:true},
52 52 {key:"revision",label:"${_('Revision')}",sortable:true,
53 53 sortOptions: { sortFunction: revisionSort }},
54 54 {key:"compare",label:"${_('Compare')}",sortable:false,},
55 55 ];
56 56
57 57 var myDataSource = new YAHOO.util.DataSource(YUD.get("tags_data"));
58 58
59 59 myDataSource.responseType = YAHOO.util.DataSource.TYPE_HTMLTABLE;
60 60
61 61 myDataSource.responseSchema = {
62 62 fields: [
63 63 {key:"name"},
64 64 {key:"date"},
65 65 {key:"author"},
66 66 {key:"revision"},
67 67 {key:"compare"},
68 68 ]
69 69 };
70 70
71 71 var myDataTable = new YAHOO.widget.DataTable("table_wrap", myColumnDefs, myDataSource,
72 72 {
73 73 sortedBy:{key:"name",dir:"asc"},
74 74 MSG_SORTASC:"${_('Click to sort ascending')}",
75 75 MSG_SORTDESC:"${_('Click to sort descending')}",
76 76 MSG_EMPTY:"${_('No records found.')}",
77 77 MSG_ERROR:"${_('Data error.')}",
78 78 MSG_LOADING:"${_('Loading...')}",
79 79 }
80 80 );
81 81 myDataTable.subscribe('postRenderEvent',function(oArgs) {
82 82 tooltip_activate();
83 83 var func = function(node){
84 84 return node.parentNode.parentNode.parentNode.parentNode.parentNode;
85 85 }
86 86 q_filter('q_filter_tags',YUQ('div.table tr td .logtags .tagtag a'),func);
87 87 });
88 88
89 89 </script>
90 90 </%def>
General Comments 0
You need to be logged in to leave comments. Login now