##// END OF EJS Templates
javascript: remove nice trailing comma to please IE8 (Issue #39)
Mads Kiilerich -
r4516:b3f12c35 default
parent child Browse files
Show More
@@ -1,2178 +1,2178 b''
1 /**
1 /**
2 Kallithea JS Files
2 Kallithea JS Files
3 **/
3 **/
4
4
5 if (typeof console == "undefined" || typeof console.log == "undefined"){
5 if (typeof console == "undefined" || typeof console.log == "undefined"){
6 console = { log: function() {} }
6 console = { log: function() {} }
7 }
7 }
8
8
9 /**
9 /**
10 * INJECT .format function into String
10 * INJECT .format function into String
11 * Usage: "My name is {0} {1}".format("Johny","Bravo")
11 * Usage: "My name is {0} {1}".format("Johny","Bravo")
12 * Return "My name is Johny Bravo"
12 * Return "My name is Johny Bravo"
13 * Inspired by https://gist.github.com/1049426
13 * Inspired by https://gist.github.com/1049426
14 */
14 */
15 String.prototype.format = function() {
15 String.prototype.format = function() {
16 function format() {
16 function format() {
17 var str = this;
17 var str = this;
18 var len = arguments.length+1;
18 var len = arguments.length+1;
19 var safe = undefined;
19 var safe = undefined;
20 var arg = undefined;
20 var arg = undefined;
21
21
22 // For each {0} {1} {n...} replace with the argument in that position. If
22 // For each {0} {1} {n...} replace with the argument in that position. If
23 // the argument is an object or an array it will be stringified to JSON.
23 // the argument is an object or an array it will be stringified to JSON.
24 for (var i=0; i < len; arg = arguments[i++]) {
24 for (var i=0; i < len; arg = arguments[i++]) {
25 safe = typeof arg === 'object' ? JSON.stringify(arg) : arg;
25 safe = typeof arg === 'object' ? JSON.stringify(arg) : arg;
26 str = str.replace(RegExp('\\{'+(i-1)+'\\}', 'g'), safe);
26 str = str.replace(RegExp('\\{'+(i-1)+'\\}', 'g'), safe);
27 }
27 }
28 return str;
28 return str;
29 }
29 }
30
30
31 // Save a reference of what may already exist under the property native.
31 // Save a reference of what may already exist under the property native.
32 // Allows for doing something like: if("".format.native) { /* use native */ }
32 // Allows for doing something like: if("".format.native) { /* use native */ }
33 format.native = String.prototype.format;
33 format.native = String.prototype.format;
34
34
35 // Replace the prototype property
35 // Replace the prototype property
36 return format;
36 return format;
37
37
38 }();
38 }();
39
39
40 String.prototype.strip = function(char) {
40 String.prototype.strip = function(char) {
41 if(char === undefined){
41 if(char === undefined){
42 char = '\\s';
42 char = '\\s';
43 }
43 }
44 return this.replace(new RegExp('^'+char+'+|'+char+'+$','g'), '');
44 return this.replace(new RegExp('^'+char+'+|'+char+'+$','g'), '');
45 }
45 }
46
46
47 String.prototype.lstrip = function(char) {
47 String.prototype.lstrip = function(char) {
48 if(char === undefined){
48 if(char === undefined){
49 char = '\\s';
49 char = '\\s';
50 }
50 }
51 return this.replace(new RegExp('^'+char+'+'),'');
51 return this.replace(new RegExp('^'+char+'+'),'');
52 }
52 }
53
53
54 String.prototype.rstrip = function(char) {
54 String.prototype.rstrip = function(char) {
55 if(char === undefined){
55 if(char === undefined){
56 char = '\\s';
56 char = '\\s';
57 }
57 }
58 return this.replace(new RegExp(''+char+'+$'),'');
58 return this.replace(new RegExp(''+char+'+$'),'');
59 }
59 }
60
60
61 /* https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/indexOf#Polyfill
61 /* https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/indexOf#Polyfill
62 under MIT license / public domain, see
62 under MIT license / public domain, see
63 https://developer.mozilla.org/en-US/docs/MDN/About#Copyrights_and_licenses */
63 https://developer.mozilla.org/en-US/docs/MDN/About#Copyrights_and_licenses */
64 if(!Array.prototype.indexOf) {
64 if(!Array.prototype.indexOf) {
65 Array.prototype.indexOf = function (searchElement, fromIndex) {
65 Array.prototype.indexOf = function (searchElement, fromIndex) {
66 if ( this === undefined || this === null ) {
66 if ( this === undefined || this === null ) {
67 throw new TypeError( '"this" is null or not defined' );
67 throw new TypeError( '"this" is null or not defined' );
68 }
68 }
69
69
70 var length = this.length >>> 0; // Hack to convert object.length to a UInt32
70 var length = this.length >>> 0; // Hack to convert object.length to a UInt32
71
71
72 fromIndex = +fromIndex || 0;
72 fromIndex = +fromIndex || 0;
73
73
74 if (Math.abs(fromIndex) === Infinity) {
74 if (Math.abs(fromIndex) === Infinity) {
75 fromIndex = 0;
75 fromIndex = 0;
76 }
76 }
77
77
78 if (fromIndex < 0) {
78 if (fromIndex < 0) {
79 fromIndex += length;
79 fromIndex += length;
80 if (fromIndex < 0) {
80 if (fromIndex < 0) {
81 fromIndex = 0;
81 fromIndex = 0;
82 }
82 }
83 }
83 }
84
84
85 for (;fromIndex < length; fromIndex++) {
85 for (;fromIndex < length; fromIndex++) {
86 if (this[fromIndex] === searchElement) {
86 if (this[fromIndex] === searchElement) {
87 return fromIndex;
87 return fromIndex;
88 }
88 }
89 }
89 }
90
90
91 return -1;
91 return -1;
92 };
92 };
93 }
93 }
94
94
95 /* https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter#Compatibility
95 /* https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter#Compatibility
96 under MIT license / public domain, see
96 under MIT license / public domain, see
97 https://developer.mozilla.org/en-US/docs/MDN/About#Copyrights_and_licenses */
97 https://developer.mozilla.org/en-US/docs/MDN/About#Copyrights_and_licenses */
98 if (!Array.prototype.filter)
98 if (!Array.prototype.filter)
99 {
99 {
100 Array.prototype.filter = function(fun /*, thisArg */)
100 Array.prototype.filter = function(fun /*, thisArg */)
101 {
101 {
102 "use strict";
102 "use strict";
103
103
104 if (this === void 0 || this === null)
104 if (this === void 0 || this === null)
105 throw new TypeError();
105 throw new TypeError();
106
106
107 var t = Object(this);
107 var t = Object(this);
108 var len = t.length >>> 0;
108 var len = t.length >>> 0;
109 if (typeof fun !== "function")
109 if (typeof fun !== "function")
110 throw new TypeError();
110 throw new TypeError();
111
111
112 var res = [];
112 var res = [];
113 var thisArg = arguments.length >= 2 ? arguments[1] : void 0;
113 var thisArg = arguments.length >= 2 ? arguments[1] : void 0;
114 for (var i = 0; i < len; i++)
114 for (var i = 0; i < len; i++)
115 {
115 {
116 if (i in t)
116 if (i in t)
117 {
117 {
118 var val = t[i];
118 var val = t[i];
119
119
120 // NOTE: Technically this should Object.defineProperty at
120 // NOTE: Technically this should Object.defineProperty at
121 // the next index, as push can be affected by
121 // the next index, as push can be affected by
122 // properties on Object.prototype and Array.prototype.
122 // properties on Object.prototype and Array.prototype.
123 // But that method's new, and collisions should be
123 // But that method's new, and collisions should be
124 // rare, so use the more-compatible alternative.
124 // rare, so use the more-compatible alternative.
125 if (fun.call(thisArg, val, i, t))
125 if (fun.call(thisArg, val, i, t))
126 res.push(val);
126 res.push(val);
127 }
127 }
128 }
128 }
129
129
130 return res;
130 return res;
131 };
131 };
132 }
132 }
133
133
134 /**
134 /**
135 * A customized version of PyRoutes.JS from https://pypi.python.org/pypi/pyroutes.js/
135 * A customized version of PyRoutes.JS from https://pypi.python.org/pypi/pyroutes.js/
136 * which is copyright Stephane Klein and was made available under the BSD License.
136 * which is copyright Stephane Klein and was made available under the BSD License.
137 *
137 *
138 * Usage pyroutes.url('mark_error_fixed',{"error_id":error_id}) // /mark_error_fixed/<error_id>
138 * Usage pyroutes.url('mark_error_fixed',{"error_id":error_id}) // /mark_error_fixed/<error_id>
139 */
139 */
140 var pyroutes = (function() {
140 var pyroutes = (function() {
141 // access global map defined in special file pyroutes
141 // access global map defined in special file pyroutes
142 var matchlist = PROUTES_MAP;
142 var matchlist = PROUTES_MAP;
143 var sprintf = (function() {
143 var sprintf = (function() {
144 function get_type(variable) {
144 function get_type(variable) {
145 return Object.prototype.toString.call(variable).slice(8, -1).toLowerCase();
145 return Object.prototype.toString.call(variable).slice(8, -1).toLowerCase();
146 }
146 }
147 function str_repeat(input, multiplier) {
147 function str_repeat(input, multiplier) {
148 for (var output = []; multiplier > 0; output[--multiplier] = input) {/* do nothing */}
148 for (var output = []; multiplier > 0; output[--multiplier] = input) {/* do nothing */}
149 return output.join('');
149 return output.join('');
150 }
150 }
151
151
152 var str_format = function() {
152 var str_format = function() {
153 if (!str_format.cache.hasOwnProperty(arguments[0])) {
153 if (!str_format.cache.hasOwnProperty(arguments[0])) {
154 str_format.cache[arguments[0]] = str_format.parse(arguments[0]);
154 str_format.cache[arguments[0]] = str_format.parse(arguments[0]);
155 }
155 }
156 return str_format.format.call(null, str_format.cache[arguments[0]], arguments);
156 return str_format.format.call(null, str_format.cache[arguments[0]], arguments);
157 };
157 };
158
158
159 str_format.format = function(parse_tree, argv) {
159 str_format.format = function(parse_tree, argv) {
160 var cursor = 1, tree_length = parse_tree.length, node_type = '', arg, output = [], i, k, match, pad, pad_character, pad_length;
160 var cursor = 1, tree_length = parse_tree.length, node_type = '', arg, output = [], i, k, match, pad, pad_character, pad_length;
161 for (i = 0; i < tree_length; i++) {
161 for (i = 0; i < tree_length; i++) {
162 node_type = get_type(parse_tree[i]);
162 node_type = get_type(parse_tree[i]);
163 if (node_type === 'string') {
163 if (node_type === 'string') {
164 output.push(parse_tree[i]);
164 output.push(parse_tree[i]);
165 }
165 }
166 else if (node_type === 'array') {
166 else if (node_type === 'array') {
167 match = parse_tree[i]; // convenience purposes only
167 match = parse_tree[i]; // convenience purposes only
168 if (match[2]) { // keyword argument
168 if (match[2]) { // keyword argument
169 arg = argv[cursor];
169 arg = argv[cursor];
170 for (k = 0; k < match[2].length; k++) {
170 for (k = 0; k < match[2].length; k++) {
171 if (!arg.hasOwnProperty(match[2][k])) {
171 if (!arg.hasOwnProperty(match[2][k])) {
172 throw(sprintf('[sprintf] property "%s" does not exist', match[2][k]));
172 throw(sprintf('[sprintf] property "%s" does not exist', match[2][k]));
173 }
173 }
174 arg = arg[match[2][k]];
174 arg = arg[match[2][k]];
175 }
175 }
176 }
176 }
177 else if (match[1]) { // positional argument (explicit)
177 else if (match[1]) { // positional argument (explicit)
178 arg = argv[match[1]];
178 arg = argv[match[1]];
179 }
179 }
180 else { // positional argument (implicit)
180 else { // positional argument (implicit)
181 arg = argv[cursor++];
181 arg = argv[cursor++];
182 }
182 }
183
183
184 if (/[^s]/.test(match[8]) && (get_type(arg) != 'number')) {
184 if (/[^s]/.test(match[8]) && (get_type(arg) != 'number')) {
185 throw(sprintf('[sprintf] expecting number but found %s', get_type(arg)));
185 throw(sprintf('[sprintf] expecting number but found %s', get_type(arg)));
186 }
186 }
187 switch (match[8]) {
187 switch (match[8]) {
188 case 'b': arg = arg.toString(2); break;
188 case 'b': arg = arg.toString(2); break;
189 case 'c': arg = String.fromCharCode(arg); break;
189 case 'c': arg = String.fromCharCode(arg); break;
190 case 'd': arg = parseInt(arg, 10); break;
190 case 'd': arg = parseInt(arg, 10); break;
191 case 'e': arg = match[7] ? arg.toExponential(match[7]) : arg.toExponential(); break;
191 case 'e': arg = match[7] ? arg.toExponential(match[7]) : arg.toExponential(); break;
192 case 'f': arg = match[7] ? parseFloat(arg).toFixed(match[7]) : parseFloat(arg); break;
192 case 'f': arg = match[7] ? parseFloat(arg).toFixed(match[7]) : parseFloat(arg); break;
193 case 'o': arg = arg.toString(8); break;
193 case 'o': arg = arg.toString(8); break;
194 case 's': arg = ((arg = String(arg)) && match[7] ? arg.substring(0, match[7]) : arg); break;
194 case 's': arg = ((arg = String(arg)) && match[7] ? arg.substring(0, match[7]) : arg); break;
195 case 'u': arg = Math.abs(arg); break;
195 case 'u': arg = Math.abs(arg); break;
196 case 'x': arg = arg.toString(16); break;
196 case 'x': arg = arg.toString(16); break;
197 case 'X': arg = arg.toString(16).toUpperCase(); break;
197 case 'X': arg = arg.toString(16).toUpperCase(); break;
198 }
198 }
199 arg = (/[def]/.test(match[8]) && match[3] && arg >= 0 ? '+'+ arg : arg);
199 arg = (/[def]/.test(match[8]) && match[3] && arg >= 0 ? '+'+ arg : arg);
200 pad_character = match[4] ? match[4] == '0' ? '0' : match[4].charAt(1) : ' ';
200 pad_character = match[4] ? match[4] == '0' ? '0' : match[4].charAt(1) : ' ';
201 pad_length = match[6] - String(arg).length;
201 pad_length = match[6] - String(arg).length;
202 pad = match[6] ? str_repeat(pad_character, pad_length) : '';
202 pad = match[6] ? str_repeat(pad_character, pad_length) : '';
203 output.push(match[5] ? arg + pad : pad + arg);
203 output.push(match[5] ? arg + pad : pad + arg);
204 }
204 }
205 }
205 }
206 return output.join('');
206 return output.join('');
207 };
207 };
208
208
209 str_format.cache = {};
209 str_format.cache = {};
210
210
211 str_format.parse = function(fmt) {
211 str_format.parse = function(fmt) {
212 var _fmt = fmt, match = [], parse_tree = [], arg_names = 0;
212 var _fmt = fmt, match = [], parse_tree = [], arg_names = 0;
213 while (_fmt) {
213 while (_fmt) {
214 if ((match = /^[^\x25]+/.exec(_fmt)) !== null) {
214 if ((match = /^[^\x25]+/.exec(_fmt)) !== null) {
215 parse_tree.push(match[0]);
215 parse_tree.push(match[0]);
216 }
216 }
217 else if ((match = /^\x25{2}/.exec(_fmt)) !== null) {
217 else if ((match = /^\x25{2}/.exec(_fmt)) !== null) {
218 parse_tree.push('%');
218 parse_tree.push('%');
219 }
219 }
220 else if ((match = /^\x25(?:([1-9]\d*)\$|\(([^\)]+)\))?(\+)?(0|'[^$])?(-)?(\d+)?(?:\.(\d+))?([b-fosuxX])/.exec(_fmt)) !== null) {
220 else if ((match = /^\x25(?:([1-9]\d*)\$|\(([^\)]+)\))?(\+)?(0|'[^$])?(-)?(\d+)?(?:\.(\d+))?([b-fosuxX])/.exec(_fmt)) !== null) {
221 if (match[2]) {
221 if (match[2]) {
222 arg_names |= 1;
222 arg_names |= 1;
223 var field_list = [], replacement_field = match[2], field_match = [];
223 var field_list = [], replacement_field = match[2], field_match = [];
224 if ((field_match = /^([a-z_][a-z_\d]*)/i.exec(replacement_field)) !== null) {
224 if ((field_match = /^([a-z_][a-z_\d]*)/i.exec(replacement_field)) !== null) {
225 field_list.push(field_match[1]);
225 field_list.push(field_match[1]);
226 while ((replacement_field = replacement_field.substring(field_match[0].length)) !== '') {
226 while ((replacement_field = replacement_field.substring(field_match[0].length)) !== '') {
227 if ((field_match = /^\.([a-z_][a-z_\d]*)/i.exec(replacement_field)) !== null) {
227 if ((field_match = /^\.([a-z_][a-z_\d]*)/i.exec(replacement_field)) !== null) {
228 field_list.push(field_match[1]);
228 field_list.push(field_match[1]);
229 }
229 }
230 else if ((field_match = /^\[(\d+)\]/.exec(replacement_field)) !== null) {
230 else if ((field_match = /^\[(\d+)\]/.exec(replacement_field)) !== null) {
231 field_list.push(field_match[1]);
231 field_list.push(field_match[1]);
232 }
232 }
233 else {
233 else {
234 throw('[sprintf] huh?');
234 throw('[sprintf] huh?');
235 }
235 }
236 }
236 }
237 }
237 }
238 else {
238 else {
239 throw('[sprintf] huh?');
239 throw('[sprintf] huh?');
240 }
240 }
241 match[2] = field_list;
241 match[2] = field_list;
242 }
242 }
243 else {
243 else {
244 arg_names |= 2;
244 arg_names |= 2;
245 }
245 }
246 if (arg_names === 3) {
246 if (arg_names === 3) {
247 throw('[sprintf] mixing positional and named placeholders is not (yet) supported');
247 throw('[sprintf] mixing positional and named placeholders is not (yet) supported');
248 }
248 }
249 parse_tree.push(match);
249 parse_tree.push(match);
250 }
250 }
251 else {
251 else {
252 throw('[sprintf] huh?');
252 throw('[sprintf] huh?');
253 }
253 }
254 _fmt = _fmt.substring(match[0].length);
254 _fmt = _fmt.substring(match[0].length);
255 }
255 }
256 return parse_tree;
256 return parse_tree;
257 };
257 };
258
258
259 return str_format;
259 return str_format;
260 })();
260 })();
261
261
262 var vsprintf = function(fmt, argv) {
262 var vsprintf = function(fmt, argv) {
263 argv.unshift(fmt);
263 argv.unshift(fmt);
264 return sprintf.apply(null, argv);
264 return sprintf.apply(null, argv);
265 };
265 };
266 return {
266 return {
267 'url': function(route_name, params) {
267 'url': function(route_name, params) {
268 var result = route_name;
268 var result = route_name;
269 if (typeof(params) != 'object'){
269 if (typeof(params) != 'object'){
270 params = {};
270 params = {};
271 }
271 }
272 if (matchlist.hasOwnProperty(route_name)) {
272 if (matchlist.hasOwnProperty(route_name)) {
273 var route = matchlist[route_name];
273 var route = matchlist[route_name];
274 // param substitution
274 // param substitution
275 for(var i=0; i < route[1].length; i++) {
275 for(var i=0; i < route[1].length; i++) {
276 if (!params.hasOwnProperty(route[1][i]))
276 if (!params.hasOwnProperty(route[1][i]))
277 throw new Error(route[1][i] + ' missing in "' + route_name + '" route generation');
277 throw new Error(route[1][i] + ' missing in "' + route_name + '" route generation');
278 }
278 }
279 result = sprintf(route[0], params);
279 result = sprintf(route[0], params);
280
280
281 var ret = [];
281 var ret = [];
282 //extra params => GET
282 //extra params => GET
283 for(param in params){
283 for(param in params){
284 if (route[1].indexOf(param) == -1){
284 if (route[1].indexOf(param) == -1){
285 ret.push(encodeURIComponent(param) + "=" + encodeURIComponent(params[param]));
285 ret.push(encodeURIComponent(param) + "=" + encodeURIComponent(params[param]));
286 }
286 }
287 }
287 }
288 var _parts = ret.join("&");
288 var _parts = ret.join("&");
289 if(_parts){
289 if(_parts){
290 result = result +'?'+ _parts
290 result = result +'?'+ _parts
291 }
291 }
292 }
292 }
293
293
294 return result;
294 return result;
295 },
295 },
296 'register': function(route_name, route_tmpl, req_params) {
296 'register': function(route_name, route_tmpl, req_params) {
297 if (typeof(req_params) != 'object') {
297 if (typeof(req_params) != 'object') {
298 req_params = [];
298 req_params = [];
299 }
299 }
300 //fix escape
300 //fix escape
301 route_tmpl = unescape(route_tmpl);
301 route_tmpl = unescape(route_tmpl);
302 keys = [];
302 keys = [];
303 for (var i=0; i < req_params.length; i++) {
303 for (var i=0; i < req_params.length; i++) {
304 keys.push(req_params[i])
304 keys.push(req_params[i])
305 }
305 }
306 matchlist[route_name] = [
306 matchlist[route_name] = [
307 route_tmpl,
307 route_tmpl,
308 keys
308 keys
309 ]
309 ]
310 },
310 },
311 '_routes': function(){
311 '_routes': function(){
312 return matchlist;
312 return matchlist;
313 }
313 }
314 }
314 }
315 })();
315 })();
316
316
317
317
318 /**
318 /**
319 * GLOBAL YUI Shortcuts
319 * GLOBAL YUI Shortcuts
320 */
320 */
321 var YUC = YAHOO.util.Connect;
321 var YUC = YAHOO.util.Connect;
322 var YUD = YAHOO.util.Dom;
322 var YUD = YAHOO.util.Dom;
323 var YUE = YAHOO.util.Event;
323 var YUE = YAHOO.util.Event;
324 var YUQ = YAHOO.util.Selector.query;
324 var YUQ = YAHOO.util.Selector.query;
325
325
326 /* Invoke all functions in callbacks */
326 /* Invoke all functions in callbacks */
327 var _run_callbacks = function(callbacks){
327 var _run_callbacks = function(callbacks){
328 if (callbacks !== undefined){
328 if (callbacks !== undefined){
329 var _l = callbacks.length;
329 var _l = callbacks.length;
330 for (var i=0;i<_l;i++){
330 for (var i=0;i<_l;i++){
331 var func = callbacks[i];
331 var func = callbacks[i];
332 if(typeof(func)=='function'){
332 if(typeof(func)=='function'){
333 try{
333 try{
334 func();
334 func();
335 }catch (err){};
335 }catch (err){};
336 }
336 }
337 }
337 }
338 }
338 }
339 }
339 }
340
340
341 /**
341 /**
342 * turns objects into GET query string
342 * turns objects into GET query string
343 */
343 */
344 var _toQueryString = function(o) {
344 var _toQueryString = function(o) {
345 if(typeof o !== 'object') {
345 if(typeof o !== 'object') {
346 return false;
346 return false;
347 }
347 }
348 var _p, _qs = [];
348 var _p, _qs = [];
349 for(_p in o) {
349 for(_p in o) {
350 _qs.push(encodeURIComponent(_p) + '=' + encodeURIComponent(o[_p]));
350 _qs.push(encodeURIComponent(_p) + '=' + encodeURIComponent(o[_p]));
351 }
351 }
352 return _qs.join('&');
352 return _qs.join('&');
353 };
353 };
354
354
355 /**
355 /**
356 * Load HTML into DOM using Ajax
356 * Load HTML into DOM using Ajax
357 *
357 *
358 * @param $target: load html async and place it (or an error message) here
358 * @param $target: load html async and place it (or an error message) here
359 * @param success: success callback function
359 * @param success: success callback function
360 * @param args: query parameters to pass to url
360 * @param args: query parameters to pass to url
361 */
361 */
362 function asynchtml(url, $target, success, args){
362 function asynchtml(url, $target, success, args){
363 if(args===undefined){
363 if(args===undefined){
364 args=null;
364 args=null;
365 }
365 }
366 $target.html(_TM['Loading ...']).css('opacity','0.3');
366 $target.html(_TM['Loading ...']).css('opacity','0.3');
367
367
368 $.ajax({url: url, data: args, headers: {'X-PARTIAL-XHR': '1'}, cache: false, dataType: 'html'})
368 $.ajax({url: url, data: args, headers: {'X-PARTIAL-XHR': '1'}, cache: false, dataType: 'html'})
369 .done(function(html) {
369 .done(function(html) {
370 $target.html(html);
370 $target.html(html);
371 $target.css('opacity','1.0');
371 $target.css('opacity','1.0');
372 //execute the given original callback
372 //execute the given original callback
373 if (success !== undefined && success) {
373 if (success !== undefined && success) {
374 success();
374 success();
375 }
375 }
376 })
376 })
377 .fail(function(jqXHR, textStatus, errorThrown) {
377 .fail(function(jqXHR, textStatus, errorThrown) {
378 console.log('Ajax failure: ' + textStatus);
378 console.log('Ajax failure: ' + textStatus);
379 $target.html('<span class="error_red">ERROR: {0}</span>'.format(textStatus));
379 $target.html('<span class="error_red">ERROR: {0}</span>'.format(textStatus));
380 $target.css('opacity','1.0');
380 $target.css('opacity','1.0');
381 })
381 })
382 ;
382 ;
383 };
383 };
384
384
385 var ajaxGET = function(url,success) {
385 var ajaxGET = function(url,success) {
386 // Set special header for ajax == HTTP_X_PARTIAL_XHR
386 // Set special header for ajax == HTTP_X_PARTIAL_XHR
387 YUC.initHeader('X-PARTIAL-XHR',true);
387 YUC.initHeader('X-PARTIAL-XHR',true);
388
388
389 var sUrl = url;
389 var sUrl = url;
390 var callback = {
390 var callback = {
391 success: success,
391 success: success,
392 failure: function (o) {
392 failure: function (o) {
393 if (o.status != 0) {
393 if (o.status != 0) {
394 alert("Ajax GET error: " + o.statusText);
394 alert("Ajax GET error: " + o.statusText);
395 };
395 };
396 },
396 }
397 };
397 };
398
398
399 var request = YAHOO.util.Connect.asyncRequest('GET', sUrl, callback);
399 var request = YAHOO.util.Connect.asyncRequest('GET', sUrl, callback);
400 return request;
400 return request;
401 };
401 };
402
402
403 var ajaxPOST = function(url,postData,success) {
403 var ajaxPOST = function(url,postData,success) {
404 // Set special header for ajax == HTTP_X_PARTIAL_XHR
404 // Set special header for ajax == HTTP_X_PARTIAL_XHR
405 YUC.initHeader('X-PARTIAL-XHR',true);
405 YUC.initHeader('X-PARTIAL-XHR',true);
406
406
407 var sUrl = url;
407 var sUrl = url;
408 var callback = {
408 var callback = {
409 success: success,
409 success: success,
410 failure: function (o) {
410 failure: function (o) {
411 alert("Ajax POST error: " + o.statusText);
411 alert("Ajax POST error: " + o.statusText);
412 },
412 }
413 };
413 };
414 var postData = _toQueryString(postData);
414 var postData = _toQueryString(postData);
415 var request = YAHOO.util.Connect.asyncRequest('POST', sUrl, callback, postData);
415 var request = YAHOO.util.Connect.asyncRequest('POST', sUrl, callback, postData);
416 return request;
416 return request;
417 };
417 };
418
418
419
419
420 /**
420 /**
421 * activate .show_more links
421 * activate .show_more links
422 * the .show_more must have an id that is the the id of an element to hide prefixed with _
422 * the .show_more must have an id that is the the id of an element to hide prefixed with _
423 * the parentnode will be displayed
423 * the parentnode will be displayed
424 */
424 */
425 var show_more_event = function(){
425 var show_more_event = function(){
426 $('.show_more').click(function(e){
426 $('.show_more').click(function(e){
427 var el = e.currentTarget;
427 var el = e.currentTarget;
428 $('#' + el.id.substring(1)).hide();
428 $('#' + el.id.substring(1)).hide();
429 $(el.parentNode).show();
429 $(el.parentNode).show();
430 });
430 });
431 };
431 };
432
432
433 /**
433 /**
434 * activate .lazy-cs mouseover for showing changeset tooltip
434 * activate .lazy-cs mouseover for showing changeset tooltip
435 */
435 */
436 var show_changeset_tooltip = function(){
436 var show_changeset_tooltip = function(){
437 $('.lazy-cs').mouseover(function(e){
437 $('.lazy-cs').mouseover(function(e){
438 var $target = $(e.currentTarget);
438 var $target = $(e.currentTarget);
439 var rid = $target.attr('raw_id');
439 var rid = $target.attr('raw_id');
440 var repo_name = $target.attr('repo_name');
440 var repo_name = $target.attr('repo_name');
441 if(rid && !$target.hasClass('tooltip')){
441 if(rid && !$target.hasClass('tooltip')){
442 _show_tooltip(e, _TM['loading ...']);
442 _show_tooltip(e, _TM['loading ...']);
443 var url = pyroutes.url('changeset_info', {"repo_name": repo_name, "revision": rid});
443 var url = pyroutes.url('changeset_info', {"repo_name": repo_name, "revision": rid});
444 ajaxGET(url, function(o){
444 ajaxGET(url, function(o){
445 var json = JSON.parse(o.responseText);
445 var json = JSON.parse(o.responseText);
446 $target.addClass('tooltip')
446 $target.addClass('tooltip')
447 _show_tooltip(e, json['message']);
447 _show_tooltip(e, json['message']);
448 _activate_tooltip($target);
448 _activate_tooltip($target);
449 });
449 });
450 }
450 }
451 });
451 });
452 };
452 };
453
453
454 var _onSuccessFollow = function(target){
454 var _onSuccessFollow = function(target){
455 var $target = $(target);
455 var $target = $(target);
456 var $f_cnt = $('#current_followers_count');
456 var $f_cnt = $('#current_followers_count');
457 if($target.hasClass('follow')){
457 if($target.hasClass('follow')){
458 $target.attr('class', 'following');
458 $target.attr('class', 'following');
459 $target.attr('title', _TM['Stop following this repository']);
459 $target.attr('title', _TM['Stop following this repository']);
460 if($f_cnt.html()){
460 if($f_cnt.html()){
461 var cnt = Number($f_cnt.html())+1;
461 var cnt = Number($f_cnt.html())+1;
462 $f_cnt.html(cnt);
462 $f_cnt.html(cnt);
463 }
463 }
464 }
464 }
465 else{
465 else{
466 $target.attr('class', 'follow');
466 $target.attr('class', 'follow');
467 $target.attr('title', _TM['Start following this repository']);
467 $target.attr('title', _TM['Start following this repository']);
468 if($f_cnt.html()){
468 if($f_cnt.html()){
469 var cnt = Number($f_cnt.html())-1;
469 var cnt = Number($f_cnt.html())-1;
470 $f_cnt.html(cnt);
470 $f_cnt.html(cnt);
471 }
471 }
472 }
472 }
473 }
473 }
474
474
475 var toggleFollowingRepo = function(target, follows_repo_id, token, user_id){
475 var toggleFollowingRepo = function(target, follows_repo_id, token, user_id){
476 args = 'follows_repo_id='+follows_repo_id;
476 args = 'follows_repo_id='+follows_repo_id;
477 args+= '&amp;auth_token='+token;
477 args+= '&amp;auth_token='+token;
478 if(user_id != undefined){
478 if(user_id != undefined){
479 args+="&amp;user_id="+user_id;
479 args+="&amp;user_id="+user_id;
480 }
480 }
481 $.post(TOGGLE_FOLLOW_URL, args, function(data){
481 $.post(TOGGLE_FOLLOW_URL, args, function(data){
482 _onSuccessFollow(target);
482 _onSuccessFollow(target);
483 });
483 });
484 return false;
484 return false;
485 };
485 };
486
486
487 var showRepoSize = function(target, repo_name, token){
487 var showRepoSize = function(target, repo_name, token){
488 var args= 'auth_token='+token;
488 var args= 'auth_token='+token;
489
489
490 if(!$("#" + target).hasClass('loaded')){
490 if(!$("#" + target).hasClass('loaded')){
491 $("#" + target).html(_TM['Loading ...']);
491 $("#" + target).html(_TM['Loading ...']);
492 var url = pyroutes.url('repo_size', {"repo_name":repo_name});
492 var url = pyroutes.url('repo_size', {"repo_name":repo_name});
493 $.post(url, args, function(data) {
493 $.post(url, args, function(data) {
494 $("#" + target).html(data);
494 $("#" + target).html(data);
495 $("#" + target).addClass('loaded');
495 $("#" + target).addClass('loaded');
496 });
496 });
497 }
497 }
498 return false;
498 return false;
499 };
499 };
500
500
501 /**
501 /**
502 * tooltips
502 * tooltips
503 */
503 */
504
504
505 var tooltip_activate = function(){
505 var tooltip_activate = function(){
506 $(document).ready(_init_tooltip);
506 $(document).ready(_init_tooltip);
507 };
507 };
508
508
509 var _activate_tooltip = function($tt){
509 var _activate_tooltip = function($tt){
510 $tt.mouseover(_show_tooltip);
510 $tt.mouseover(_show_tooltip);
511 $tt.mousemove(_move_tooltip);
511 $tt.mousemove(_move_tooltip);
512 $tt.mouseout(_close_tooltip);
512 $tt.mouseout(_close_tooltip);
513 };
513 };
514
514
515 var _init_tooltip = function(){
515 var _init_tooltip = function(){
516 var $tipBox = $('#tip-box');
516 var $tipBox = $('#tip-box');
517 if(!$tipBox.length){
517 if(!$tipBox.length){
518 $tipBox = $('<div id="tip-box"></div>')
518 $tipBox = $('<div id="tip-box"></div>')
519 $(document.body).append($tipBox);
519 $(document.body).append($tipBox);
520 }
520 }
521
521
522 $tipBox.hide();
522 $tipBox.hide();
523 $tipBox.css('position', 'absolute');
523 $tipBox.css('position', 'absolute');
524 $tipBox.css('max-width', '600px');
524 $tipBox.css('max-width', '600px');
525
525
526 _activate_tooltip($('.tooltip'));
526 _activate_tooltip($('.tooltip'));
527 };
527 };
528
528
529 var _show_tooltip = function(e, tipText){
529 var _show_tooltip = function(e, tipText){
530 e.stopImmediatePropagation();
530 e.stopImmediatePropagation();
531 var el = e.currentTarget;
531 var el = e.currentTarget;
532 if(tipText){
532 if(tipText){
533 // just use it
533 // just use it
534 } else if(el.tagName.toLowerCase() === 'img'){
534 } else if(el.tagName.toLowerCase() === 'img'){
535 tipText = el.alt ? el.alt : '';
535 tipText = el.alt ? el.alt : '';
536 } else {
536 } else {
537 tipText = el.title ? el.title : '';
537 tipText = el.title ? el.title : '';
538 }
538 }
539
539
540 if(tipText !== ''){
540 if(tipText !== ''){
541 // save org title
541 // save org title
542 $(el).attr('tt_title', tipText);
542 $(el).attr('tt_title', tipText);
543 // reset title to not show org tooltips
543 // reset title to not show org tooltips
544 $(el).attr('title', '');
544 $(el).attr('title', '');
545
545
546 var $tipBox = $('#tip-box');
546 var $tipBox = $('#tip-box');
547 $tipBox.html(tipText);
547 $tipBox.html(tipText);
548 $tipBox.css('display', 'block');
548 $tipBox.css('display', 'block');
549 }
549 }
550 };
550 };
551
551
552 var _move_tooltip = function(e){
552 var _move_tooltip = function(e){
553 e.stopImmediatePropagation();
553 e.stopImmediatePropagation();
554 var $tipBox = $('#tip-box');
554 var $tipBox = $('#tip-box');
555 $tipBox.css('top', (e.pageY + 15) + 'px');
555 $tipBox.css('top', (e.pageY + 15) + 'px');
556 $tipBox.css('left', (e.pageX + 15) + 'px');
556 $tipBox.css('left', (e.pageX + 15) + 'px');
557 };
557 };
558
558
559 var _close_tooltip = function(e){
559 var _close_tooltip = function(e){
560 e.stopImmediatePropagation();
560 e.stopImmediatePropagation();
561 var $tipBox = $('#tip-box');
561 var $tipBox = $('#tip-box');
562 $tipBox.hide();
562 $tipBox.hide();
563 var el = e.currentTarget;
563 var el = e.currentTarget;
564 $(el).attr('title', $(el).attr('tt_title'));
564 $(el).attr('title', $(el).attr('tt_title'));
565 };
565 };
566
566
567 /**
567 /**
568 * Quick filter widget
568 * Quick filter widget
569 *
569 *
570 * @param target: filter input target
570 * @param target: filter input target
571 * @param nodes: list of nodes in html we want to filter.
571 * @param nodes: list of nodes in html we want to filter.
572 * @param display_element function that takes current node from nodes and
572 * @param display_element function that takes current node from nodes and
573 * does hide or show based on the node
573 * does hide or show based on the node
574 */
574 */
575 var q_filter = function(target, nodes, display_element){
575 var q_filter = function(target, nodes, display_element){
576 var nodes = nodes;
576 var nodes = nodes;
577 var $q_filter_field = $('#' + target);
577 var $q_filter_field = $('#' + target);
578 var F = YAHOO.namespace(target);
578 var F = YAHOO.namespace(target);
579
579
580 $q_filter_field.keyup(function(e){
580 $q_filter_field.keyup(function(e){
581 clearTimeout(F.filterTimeout);
581 clearTimeout(F.filterTimeout);
582 F.filterTimeout = setTimeout(F.updateFilter, 600);
582 F.filterTimeout = setTimeout(F.updateFilter, 600);
583 });
583 });
584
584
585 F.filterTimeout = null;
585 F.filterTimeout = null;
586
586
587 F.updateFilter = function() {
587 F.updateFilter = function() {
588 // Reset timeout
588 // Reset timeout
589 F.filterTimeout = null;
589 F.filterTimeout = null;
590
590
591 var obsolete = [];
591 var obsolete = [];
592
592
593 var req = $q_filter_field.val().toLowerCase();
593 var req = $q_filter_field.val().toLowerCase();
594
594
595 var l = nodes.length;
595 var l = nodes.length;
596 var i;
596 var i;
597 var showing = 0;
597 var showing = 0;
598
598
599 for (i=0; i<l; i++ ){
599 for (i=0; i<l; i++ ){
600 var n = nodes[i];
600 var n = nodes[i];
601 var target_element = display_element(n)
601 var target_element = display_element(n)
602 if(req && n.innerHTML.toLowerCase().indexOf(req) == -1){
602 if(req && n.innerHTML.toLowerCase().indexOf(req) == -1){
603 $(target_element).hide();
603 $(target_element).hide();
604 }
604 }
605 else{
605 else{
606 $(target_element).show();
606 $(target_element).show();
607 showing += 1;
607 showing += 1;
608 }
608 }
609 }
609 }
610
610
611 $('#repo_count').html(showing); /* FIXME: don't hardcode */
611 $('#repo_count').html(showing); /* FIXME: don't hardcode */
612 }
612 }
613 };
613 };
614
614
615 /* return jQuery expression with a tr with body in 3rd column and class cls and id named after the body */
615 /* return jQuery expression with a tr with body in 3rd column and class cls and id named after the body */
616 var _table_tr = function(cls, body){
616 var _table_tr = function(cls, body){
617 // like: <div class="comment" id="comment-8" line="o92"><div class="comment-wrapp">...
617 // like: <div class="comment" id="comment-8" line="o92"><div class="comment-wrapp">...
618 // except new inlines which are different ...
618 // except new inlines which are different ...
619 var comment_id = ($(body).attr('id') || 'comment-new').split('comment-')[1];
619 var comment_id = ($(body).attr('id') || 'comment-new').split('comment-')[1];
620 var tr_id = 'comment-tr-{0}'.format(comment_id);
620 var tr_id = 'comment-tr-{0}'.format(comment_id);
621 return $(('<tr id="{0}" class="{1}">'+
621 return $(('<tr id="{0}" class="{1}">'+
622 '<td class="lineno-inline new-inline"></td>'+
622 '<td class="lineno-inline new-inline"></td>'+
623 '<td class="lineno-inline old-inline"></td>'+
623 '<td class="lineno-inline old-inline"></td>'+
624 '<td>{2}</td>'+
624 '<td>{2}</td>'+
625 '</tr>').format(tr_id, cls, body));
625 '</tr>').format(tr_id, cls, body));
626 };
626 };
627
627
628 /** return jQuery expression with new inline form based on template **/
628 /** return jQuery expression with new inline form based on template **/
629 var _createInlineForm = function(parent_tr, f_path, line) {
629 var _createInlineForm = function(parent_tr, f_path, line) {
630 var $tmpl = $('#comment-inline-form-template').html().format(f_path, line);
630 var $tmpl = $('#comment-inline-form-template').html().format(f_path, line);
631 var $form = _table_tr('comment-form-inline', $tmpl)
631 var $form = _table_tr('comment-form-inline', $tmpl)
632
632
633 // create event for hide button
633 // create event for hide button
634 $form.find('.hide-inline-form').click(function(e) {
634 $form.find('.hide-inline-form').click(function(e) {
635 var newtr = e.currentTarget.parentNode.parentNode.parentNode.parentNode.parentNode;
635 var newtr = e.currentTarget.parentNode.parentNode.parentNode.parentNode.parentNode;
636 if($(newtr).next().hasClass('inline-comments-button')){
636 if($(newtr).next().hasClass('inline-comments-button')){
637 $(newtr).next().show();
637 $(newtr).next().show();
638 }
638 }
639 $(newtr).remove();
639 $(newtr).remove();
640 $(parent_tr).removeClass('form-open');
640 $(parent_tr).removeClass('form-open');
641 $(parent_tr).removeClass('hl-comment');
641 $(parent_tr).removeClass('hl-comment');
642 });
642 });
643
643
644 return $form
644 return $form
645 };
645 };
646
646
647 /**
647 /**
648 * Inject inline comment for an given TR. This tr should always be a .line .
648 * Inject inline comment for an given TR. This tr should always be a .line .
649 * The form will be inject after any comments.
649 * The form will be inject after any comments.
650 */
650 */
651 var injectInlineForm = function(tr){
651 var injectInlineForm = function(tr){
652 $tr = $(tr);
652 $tr = $(tr);
653 if(!$tr.hasClass('line')){
653 if(!$tr.hasClass('line')){
654 return
654 return
655 }
655 }
656 var submit_url = AJAX_COMMENT_URL;
656 var submit_url = AJAX_COMMENT_URL;
657 var $td = $tr.find('.code');
657 var $td = $tr.find('.code');
658 if($tr.hasClass('form-open') || $tr.hasClass('context') || $td.hasClass('no-comment')){
658 if($tr.hasClass('form-open') || $tr.hasClass('context') || $td.hasClass('no-comment')){
659 return
659 return
660 }
660 }
661 $tr.addClass('form-open hl-comment');
661 $tr.addClass('form-open hl-comment');
662 var $node = $tr.parent().parent().parent().find('.full_f_path');
662 var $node = $tr.parent().parent().parent().find('.full_f_path');
663 var f_path = $node.attr('path');
663 var f_path = $node.attr('path');
664 var lineno = _getLineNo(tr);
664 var lineno = _getLineNo(tr);
665 var $form = _createInlineForm(tr, f_path, lineno, submit_url);
665 var $form = _createInlineForm(tr, f_path, lineno, submit_url);
666
666
667 var $parent = $tr;
667 var $parent = $tr;
668 while ($parent.next().hasClass('inline-comments')){
668 while ($parent.next().hasClass('inline-comments')){
669 var $parent = $parent.next();
669 var $parent = $parent.next();
670 }
670 }
671 $form.insertAfter($parent);
671 $form.insertAfter($parent);
672 var $overlay = $form.find('.submitting-overlay');
672 var $overlay = $form.find('.submitting-overlay');
673 var $inlineform = $form.find('.inline-form');
673 var $inlineform = $form.find('.inline-form');
674
674
675 $form.submit(function(e){
675 $form.submit(function(e){
676 e.preventDefault();
676 e.preventDefault();
677
677
678 if(lineno === undefined){
678 if(lineno === undefined){
679 alert('Error submitting, line ' + lineno + ' not found.');
679 alert('Error submitting, line ' + lineno + ' not found.');
680 return
680 return
681 }
681 }
682 if(f_path === undefined){
682 if(f_path === undefined){
683 alert('Error submitting, file path ' + f_path + ' not found.');
683 alert('Error submitting, file path ' + f_path + ' not found.');
684 return
684 return
685 }
685 }
686
686
687 var text = $('#text_'+lineno).val();
687 var text = $('#text_'+lineno).val();
688 if(text == ""){
688 if(text == ""){
689 return
689 return
690 }
690 }
691
691
692 $overlay.show();
692 $overlay.show();
693
693
694 var success = function(o){
694 var success = function(o){
695 $tr.removeClass('form-open');
695 $tr.removeClass('form-open');
696 $form.remove();
696 $form.remove();
697 var json_data = JSON.parse(o.responseText);
697 var json_data = JSON.parse(o.responseText);
698 _renderInlineComment(json_data);
698 _renderInlineComment(json_data);
699 };
699 };
700 var postData = {
700 var postData = {
701 'text': text,
701 'text': text,
702 'f_path': f_path,
702 'f_path': f_path,
703 'line': lineno
703 'line': lineno
704 };
704 };
705 ajaxPOST(submit_url, postData, success);
705 ajaxPOST(submit_url, postData, success);
706 });
706 });
707
707
708 $('#preview-btn_'+lineno).click(function(e){
708 $('#preview-btn_'+lineno).click(function(e){
709 var text = $('#text_'+lineno).val();
709 var text = $('#text_'+lineno).val();
710 if(!text){
710 if(!text){
711 return
711 return
712 }
712 }
713 $('#preview-box_'+lineno).addClass('unloaded');
713 $('#preview-box_'+lineno).addClass('unloaded');
714 $('#preview-box_'+lineno).html(_TM['Loading ...']);
714 $('#preview-box_'+lineno).html(_TM['Loading ...']);
715 $('#edit-container_'+lineno).hide();
715 $('#edit-container_'+lineno).hide();
716 $('#edit-btn_'+lineno).show();
716 $('#edit-btn_'+lineno).show();
717 $('#preview-container_'+lineno).show();
717 $('#preview-container_'+lineno).show();
718 $('#preview-btn_'+lineno).hide();
718 $('#preview-btn_'+lineno).hide();
719
719
720 var url = pyroutes.url('changeset_comment_preview', {'repo_name': REPO_NAME});
720 var url = pyroutes.url('changeset_comment_preview', {'repo_name': REPO_NAME});
721 var post_data = {'text': text};
721 var post_data = {'text': text};
722 ajaxPOST(url, post_data, function(o){
722 ajaxPOST(url, post_data, function(o){
723 $('#preview-box_'+lineno).html(o.responseText);
723 $('#preview-box_'+lineno).html(o.responseText);
724 $('#preview-box_'+lineno).removeClass('unloaded');
724 $('#preview-box_'+lineno).removeClass('unloaded');
725 })
725 })
726 })
726 })
727 $('#edit-btn_'+lineno).click(function(e){
727 $('#edit-btn_'+lineno).click(function(e){
728 $('#edit-container_'+lineno).show();
728 $('#edit-container_'+lineno).show();
729 $('#edit-btn_'+lineno).hide();
729 $('#edit-btn_'+lineno).hide();
730 $('#preview-container_'+lineno).hide();
730 $('#preview-container_'+lineno).hide();
731 $('#preview-btn_'+lineno).show();
731 $('#preview-btn_'+lineno).show();
732 })
732 })
733
733
734 setTimeout(function(){
734 setTimeout(function(){
735 // callbacks
735 // callbacks
736 tooltip_activate();
736 tooltip_activate();
737 MentionsAutoComplete('text_'+lineno, 'mentions_container_'+lineno,
737 MentionsAutoComplete('text_'+lineno, 'mentions_container_'+lineno,
738 _USERS_AC_DATA, _GROUPS_AC_DATA);
738 _USERS_AC_DATA, _GROUPS_AC_DATA);
739 $('#text_'+lineno).focus();
739 $('#text_'+lineno).focus();
740 },10)
740 },10)
741 };
741 };
742
742
743 var deleteComment = function(comment_id){
743 var deleteComment = function(comment_id){
744 var url = AJAX_COMMENT_DELETE_URL.replace('__COMMENT_ID__',comment_id);
744 var url = AJAX_COMMENT_DELETE_URL.replace('__COMMENT_ID__',comment_id);
745 var postData = {'_method':'delete'};
745 var postData = {'_method':'delete'};
746 var success = function(o){
746 var success = function(o){
747 var $deleted = $('#comment-tr-'+comment_id);
747 var $deleted = $('#comment-tr-'+comment_id);
748 var $prev = $deleted.prev('tr');
748 var $prev = $deleted.prev('tr');
749 $deleted.remove();
749 $deleted.remove();
750 _placeAddButton($prev);
750 _placeAddButton($prev);
751 }
751 }
752 ajaxPOST(url,postData,success);
752 ajaxPOST(url,postData,success);
753 }
753 }
754
754
755 var _getLineNo = function(tr) {
755 var _getLineNo = function(tr) {
756 var line;
756 var line;
757 var o = $(tr).children()[0].id.split('_');
757 var o = $(tr).children()[0].id.split('_');
758 var n = $(tr).children()[1].id.split('_');
758 var n = $(tr).children()[1].id.split('_');
759
759
760 if (n.length >= 2) {
760 if (n.length >= 2) {
761 line = n[n.length-1];
761 line = n[n.length-1];
762 } else if (o.length >= 2) {
762 } else if (o.length >= 2) {
763 line = o[o.length-1];
763 line = o[o.length-1];
764 }
764 }
765
765
766 return line
766 return line
767 };
767 };
768
768
769 var _placeAddButton = function($line_tr){
769 var _placeAddButton = function($line_tr){
770 var $tr = $line_tr;
770 var $tr = $line_tr;
771 while ($tr.next().hasClass('inline-comments')){
771 while ($tr.next().hasClass('inline-comments')){
772 $tr.find('.add-comment').remove();
772 $tr.find('.add-comment').remove();
773 $tr = $tr.next();
773 $tr = $tr.next();
774 }
774 }
775 $tr.find('.add-comment').remove();
775 $tr.find('.add-comment').remove();
776 var label = TRANSLATION_MAP['Add another comment'];
776 var label = TRANSLATION_MAP['Add another comment'];
777 var $html_el = $('<div class="add-comment"><span class="btn btn-mini">{0}</span></div>'.format(label));
777 var $html_el = $('<div class="add-comment"><span class="btn btn-mini">{0}</span></div>'.format(label));
778 $html_el.click(function(e) {
778 $html_el.click(function(e) {
779 injectInlineForm($line_tr);
779 injectInlineForm($line_tr);
780 });
780 });
781 $tr.find('.comment').after($html_el);
781 $tr.find('.comment').after($html_el);
782 };
782 };
783
783
784 /**
784 /**
785 * Places the inline comment into the changeset block in proper line position
785 * Places the inline comment into the changeset block in proper line position
786 */
786 */
787 var _placeInline = function(target_id, lineno, html){
787 var _placeInline = function(target_id, lineno, html){
788 var $td = $("#{0}_{1}".format(target_id, lineno));
788 var $td = $("#{0}_{1}".format(target_id, lineno));
789 if (!$td.length){
789 if (!$td.length){
790 return false;
790 return false;
791 }
791 }
792
792
793 // check if there are comments already !
793 // check if there are comments already !
794 var $line_tr = $td.parent(); // the tr
794 var $line_tr = $td.parent(); // the tr
795 var $after_tr = $line_tr;
795 var $after_tr = $line_tr;
796 while ($after_tr.next().hasClass('inline-comments')){
796 while ($after_tr.next().hasClass('inline-comments')){
797 $after_tr = $after_tr.next();
797 $after_tr = $after_tr.next();
798 }
798 }
799 // put in the comment at the bottom
799 // put in the comment at the bottom
800 var $tr = _table_tr('inline-comments', html)
800 var $tr = _table_tr('inline-comments', html)
801 $tr.find('div.comment').addClass('inline-comment');
801 $tr.find('div.comment').addClass('inline-comment');
802 $after_tr.after($tr);
802 $after_tr.after($tr);
803
803
804 // scan nodes, and attach add button to last one
804 // scan nodes, and attach add button to last one
805 _placeAddButton($line_tr);
805 _placeAddButton($line_tr);
806 return true;
806 return true;
807 }
807 }
808
808
809 /**
809 /**
810 * make a single inline comment and place it inside
810 * make a single inline comment and place it inside
811 */
811 */
812 var _renderInlineComment = function(json_data){
812 var _renderInlineComment = function(json_data){
813 var html = json_data['rendered_text'];
813 var html = json_data['rendered_text'];
814 var lineno = json_data['line_no'];
814 var lineno = json_data['line_no'];
815 var target_id = json_data['target_id'];
815 var target_id = json_data['target_id'];
816 return _placeInline(target_id, lineno, html);
816 return _placeInline(target_id, lineno, html);
817 }
817 }
818
818
819 /**
819 /**
820 * Iterates over all the inlines, and places them inside proper blocks of data
820 * Iterates over all the inlines, and places them inside proper blocks of data
821 */
821 */
822 var renderInlineComments = function(file_comments){
822 var renderInlineComments = function(file_comments){
823 for (f in file_comments){
823 for (f in file_comments){
824 // holding all comments for a FILE
824 // holding all comments for a FILE
825 var box = file_comments[f];
825 var box = file_comments[f];
826
826
827 var target_id = $(box).attr('target_id');
827 var target_id = $(box).attr('target_id');
828 // actual comments with line numbers
828 // actual comments with line numbers
829 var comments = box.children;
829 var comments = box.children;
830 for(var i=0; i<comments.length; i++){
830 for(var i=0; i<comments.length; i++){
831 var data = {
831 var data = {
832 'rendered_text': comments[i].outerHTML,
832 'rendered_text': comments[i].outerHTML,
833 'line_no': $(comments[i]).attr('line'),
833 'line_no': $(comments[i]).attr('line'),
834 'target_id': target_id
834 'target_id': target_id
835 }
835 }
836 if (_renderInlineComment(data)) {
836 if (_renderInlineComment(data)) {
837 $(comments[i]).hide();
837 $(comments[i]).hide();
838 }else{
838 }else{
839 var txt = document.createTextNode(
839 var txt = document.createTextNode(
840 "Comment to " + YUD.getAttribute(comments[i].parentNode,'path') +
840 "Comment to " + YUD.getAttribute(comments[i].parentNode,'path') +
841 " line " + data.line_no +
841 " line " + data.line_no +
842 " which is outside the diff context:");
842 " which is outside the diff context:");
843 comments[i].insertBefore(txt, comments[i].firstChild);
843 comments[i].insertBefore(txt, comments[i].firstChild);
844 }
844 }
845 }
845 }
846 $(box).show();
846 $(box).show();
847 }
847 }
848 }
848 }
849
849
850 /**
850 /**
851 * Double link comments
851 * Double link comments
852 */
852 */
853 var linkInlineComments = function(firstlinks, comments){
853 var linkInlineComments = function(firstlinks, comments){
854 var $comments = $(comments);
854 var $comments = $(comments);
855 if ($comments.length > 0) {
855 if ($comments.length > 0) {
856 $(firstlinks).html('<a href="#{0}">First comment</a>'.format($comments.attr('id')));
856 $(firstlinks).html('<a href="#{0}">First comment</a>'.format($comments.attr('id')));
857 }
857 }
858 if ($comments.length <= 1) {
858 if ($comments.length <= 1) {
859 return;
859 return;
860 }
860 }
861
861
862 $comments.each(function(i, e){
862 $comments.each(function(i, e){
863 var prev = '';
863 var prev = '';
864 if (i > 0){
864 if (i > 0){
865 var prev_anchor = YUD.getAttribute(comments.item(i-1),'id');
865 var prev_anchor = YUD.getAttribute(comments.item(i-1),'id');
866 prev = '<a href="#{0}">Previous comment</a>'.format(prev_anchor);
866 prev = '<a href="#{0}">Previous comment</a>'.format(prev_anchor);
867 }
867 }
868 var next = '';
868 var next = '';
869 if (i+1 < comments.length){
869 if (i+1 < comments.length){
870 var next_anchor = YUD.getAttribute(comments.item(i+1),'id');
870 var next_anchor = YUD.getAttribute(comments.item(i+1),'id');
871 next = '<a href="#{0}">Next comment</a>'.format(next_anchor);
871 next = '<a href="#{0}">Next comment</a>'.format(next_anchor);
872 }
872 }
873 var $div = $(('<div class="prev-next-comment">'+
873 var $div = $(('<div class="prev-next-comment">'+
874 '<div class="prev-comment">{0}</div>'+
874 '<div class="prev-comment">{0}</div>'+
875 '<div class="next-comment">{1}</div>').format(prev, next));
875 '<div class="next-comment">{1}</div>').format(prev, next));
876 $div.prependTo(this);
876 $div.prependTo(this);
877 });
877 });
878 }
878 }
879
879
880 /* activate files.html stuff */
880 /* activate files.html stuff */
881 var fileBrowserListeners = function(current_url, node_list_url, url_base){
881 var fileBrowserListeners = function(current_url, node_list_url, url_base){
882 var current_url_branch = "?branch=__BRANCH__";
882 var current_url_branch = "?branch=__BRANCH__";
883
883
884 $('#stay_at_branch').on('click',function(e){
884 $('#stay_at_branch').on('click',function(e){
885 if(e.currentTarget.checked){
885 if(e.currentTarget.checked){
886 var uri = current_url_branch;
886 var uri = current_url_branch;
887 uri = uri.replace('__BRANCH__',e.currentTarget.value);
887 uri = uri.replace('__BRANCH__',e.currentTarget.value);
888 window.location = uri;
888 window.location = uri;
889 }
889 }
890 else{
890 else{
891 window.location = current_url;
891 window.location = current_url;
892 }
892 }
893 })
893 })
894
894
895 var $node_filter = $('#node_filter');
895 var $node_filter = $('#node_filter');
896
896
897 var filterTimeout = null;
897 var filterTimeout = null;
898 var nodes = null;
898 var nodes = null;
899
899
900 var initFilter = function(){
900 var initFilter = function(){
901 $('#node_filter_box_loading').show();
901 $('#node_filter_box_loading').show();
902 $('#search_activate_id').hide();
902 $('#search_activate_id').hide();
903 $('#add_node_id').hide();
903 $('#add_node_id').hide();
904 YUC.initHeader('X-PARTIAL-XHR',true);
904 YUC.initHeader('X-PARTIAL-XHR',true);
905 YUC.asyncRequest('GET', node_list_url, {
905 YUC.asyncRequest('GET', node_list_url, {
906 success:function(o){
906 success:function(o){
907 nodes = JSON.parse(o.responseText).nodes;
907 nodes = JSON.parse(o.responseText).nodes;
908 $('#node_filter_box_loading').hide();
908 $('#node_filter_box_loading').hide();
909 $('#node_filter_box').show();
909 $('#node_filter_box').show();
910 $node_filter.focus();
910 $node_filter.focus();
911 if($node_filter.hasClass('init')){
911 if($node_filter.hasClass('init')){
912 $node_filter.val('');
912 $node_filter.val('');
913 $node_filter.removeClass('init');
913 $node_filter.removeClass('init');
914 }
914 }
915 },
915 },
916 failure:function(o){
916 failure:function(o){
917 console.log('failed to load');
917 console.log('failed to load');
918 }
918 }
919 },null);
919 },null);
920 }
920 }
921
921
922 var updateFilter = function(e) {
922 var updateFilter = function(e) {
923 return function(){
923 return function(){
924 // Reset timeout
924 // Reset timeout
925 filterTimeout = null;
925 filterTimeout = null;
926 var query = e.currentTarget.value.toLowerCase();
926 var query = e.currentTarget.value.toLowerCase();
927 var match = [];
927 var match = [];
928 var matches = 0;
928 var matches = 0;
929 var matches_max = 20;
929 var matches_max = 20;
930 if (query != ""){
930 if (query != ""){
931 for(var i=0;i<nodes.length;i++){
931 for(var i=0;i<nodes.length;i++){
932 var pos = nodes[i].name.toLowerCase().indexOf(query)
932 var pos = nodes[i].name.toLowerCase().indexOf(query)
933 if(query && pos != -1){
933 if(query && pos != -1){
934 matches++
934 matches++
935 //show only certain amount to not kill browser
935 //show only certain amount to not kill browser
936 if (matches > matches_max){
936 if (matches > matches_max){
937 break;
937 break;
938 }
938 }
939
939
940 var n = nodes[i].name;
940 var n = nodes[i].name;
941 var t = nodes[i].type;
941 var t = nodes[i].type;
942 var n_hl = n.substring(0,pos)
942 var n_hl = n.substring(0,pos)
943 +"<b>{0}</b>".format(n.substring(pos,pos+query.length))
943 +"<b>{0}</b>".format(n.substring(pos,pos+query.length))
944 +n.substring(pos+query.length)
944 +n.substring(pos+query.length)
945 var new_url = url_base.replace('__FPATH__',n);
945 var new_url = url_base.replace('__FPATH__',n);
946 match.push('<tr><td><a class="browser-{0}" href="{1}">{2}</a></td><td colspan="5"></td></tr>'.format(t,new_url,n_hl));
946 match.push('<tr><td><a class="browser-{0}" href="{1}">{2}</a></td><td colspan="5"></td></tr>'.format(t,new_url,n_hl));
947 }
947 }
948 if(match.length >= matches_max){
948 if(match.length >= matches_max){
949 match.push('<tr><td>{0}</td><td colspan="5"></td></tr>'.format(_TM['Search truncated']));
949 match.push('<tr><td>{0}</td><td colspan="5"></td></tr>'.format(_TM['Search truncated']));
950 break;
950 break;
951 }
951 }
952 }
952 }
953 }
953 }
954 if(query != ""){
954 if(query != ""){
955 $('#tbody').hide();
955 $('#tbody').hide();
956 $('#tbody_filtered').show();
956 $('#tbody_filtered').show();
957
957
958 if (match.length==0){
958 if (match.length==0){
959 match.push('<tr><td>{0}</td><td colspan="5"></td></tr>'.format(_TM['No matching files']));
959 match.push('<tr><td>{0}</td><td colspan="5"></td></tr>'.format(_TM['No matching files']));
960 }
960 }
961
961
962 $('#tbody_filtered').html(match.join(""));
962 $('#tbody_filtered').html(match.join(""));
963 }
963 }
964 else{
964 else{
965 $('#tbody').show();
965 $('#tbody').show();
966 $('#tbody_filtered').hide();
966 $('#tbody_filtered').hide();
967 }
967 }
968 }
968 }
969 };
969 };
970
970
971 $('#filter_activate').click(function(){
971 $('#filter_activate').click(function(){
972 initFilter();
972 initFilter();
973 });
973 });
974 $node_filter.click(function(){
974 $node_filter.click(function(){
975 if($node_filter.hasClass('init')){
975 if($node_filter.hasClass('init')){
976 $node_filter.val('');
976 $node_filter.val('');
977 $node_filter.removeClass('init');
977 $node_filter.removeClass('init');
978 }
978 }
979 });
979 });
980 $node_filter.keyup(function(e){
980 $node_filter.keyup(function(e){
981 clearTimeout(filterTimeout);
981 clearTimeout(filterTimeout);
982 filterTimeout = setTimeout(updateFilter(e),600);
982 filterTimeout = setTimeout(updateFilter(e),600);
983 });
983 });
984 };
984 };
985
985
986
986
987 var initCodeMirror = function(textarea_id, resetUrl){
987 var initCodeMirror = function(textarea_id, resetUrl){
988 var myCodeMirror = CodeMirror.fromTextArea($('#' + textarea_id)[0], {
988 var myCodeMirror = CodeMirror.fromTextArea($('#' + textarea_id)[0], {
989 mode: "null",
989 mode: "null",
990 lineNumbers: true,
990 lineNumbers: true,
991 indentUnit: 4,
991 indentUnit: 4,
992 autofocus: true,
992 autofocus: true
993 });
993 });
994 $('#reset').click(function(e){
994 $('#reset').click(function(e){
995 window.location=resetUrl;
995 window.location=resetUrl;
996 });
996 });
997
997
998 $('#file_enable').click(function(){
998 $('#file_enable').click(function(){
999 $('#editor_container').show();
999 $('#editor_container').show();
1000 $('#upload_file_container').hide();
1000 $('#upload_file_container').hide();
1001 $('#filename_container').show();
1001 $('#filename_container').show();
1002 $('#set_mode_header').show();
1002 $('#set_mode_header').show();
1003 });
1003 });
1004
1004
1005 $('#upload_file_enable').click(function(){
1005 $('#upload_file_enable').click(function(){
1006 $('#editor_container').hide();
1006 $('#editor_container').hide();
1007 $('#upload_file_container').show();
1007 $('#upload_file_container').show();
1008 $('#filename_container').hide();
1008 $('#filename_container').hide();
1009 $('#set_mode_header').hide();
1009 $('#set_mode_header').hide();
1010 });
1010 });
1011
1011
1012 return myCodeMirror
1012 return myCodeMirror
1013 };
1013 };
1014
1014
1015 var setCodeMirrorMode = function(codeMirrorInstance, mode) {
1015 var setCodeMirrorMode = function(codeMirrorInstance, mode) {
1016 codeMirrorInstance.setOption("mode", mode);
1016 codeMirrorInstance.setOption("mode", mode);
1017 CodeMirror.autoLoadMode(codeMirrorInstance, mode);
1017 CodeMirror.autoLoadMode(codeMirrorInstance, mode);
1018 }
1018 }
1019
1019
1020
1020
1021 var _getIdentNode = function(n){
1021 var _getIdentNode = function(n){
1022 //iterate thrugh nodes until matching interesting node
1022 //iterate thrugh nodes until matching interesting node
1023
1023
1024 if (typeof n == 'undefined'){
1024 if (typeof n == 'undefined'){
1025 return -1
1025 return -1
1026 }
1026 }
1027
1027
1028 if(typeof n.id != "undefined" && n.id.match('L[0-9]+')){
1028 if(typeof n.id != "undefined" && n.id.match('L[0-9]+')){
1029 return n
1029 return n
1030 }
1030 }
1031 else{
1031 else{
1032 return _getIdentNode(n.parentNode);
1032 return _getIdentNode(n.parentNode);
1033 }
1033 }
1034 };
1034 };
1035
1035
1036 /* generate links for multi line selects that can be shown by files.html page_highlights.
1036 /* generate links for multi line selects that can be shown by files.html page_highlights.
1037 * This is a mouseup handler for hlcode from CodeHtmlFormatter and pygmentize */
1037 * This is a mouseup handler for hlcode from CodeHtmlFormatter and pygmentize */
1038 var getSelectionLink = function(e) {
1038 var getSelectionLink = function(e) {
1039 //get selection from start/to nodes
1039 //get selection from start/to nodes
1040 if (typeof window.getSelection != "undefined") {
1040 if (typeof window.getSelection != "undefined") {
1041 s = window.getSelection();
1041 s = window.getSelection();
1042
1042
1043 from = _getIdentNode(s.anchorNode);
1043 from = _getIdentNode(s.anchorNode);
1044 till = _getIdentNode(s.focusNode);
1044 till = _getIdentNode(s.focusNode);
1045
1045
1046 f_int = parseInt(from.id.replace('L',''));
1046 f_int = parseInt(from.id.replace('L',''));
1047 t_int = parseInt(till.id.replace('L',''));
1047 t_int = parseInt(till.id.replace('L',''));
1048
1048
1049 var yoffset = 35;
1049 var yoffset = 35;
1050 var ranges = [parseInt(from.id.replace('L','')), parseInt(till.id.replace('L',''))];
1050 var ranges = [parseInt(from.id.replace('L','')), parseInt(till.id.replace('L',''))];
1051 if (ranges[0] > ranges[1]){
1051 if (ranges[0] > ranges[1]){
1052 //highlight from bottom
1052 //highlight from bottom
1053 yoffset = -yoffset;
1053 yoffset = -yoffset;
1054 ranges = [ranges[1], ranges[0]];
1054 ranges = [ranges[1], ranges[0]];
1055 }
1055 }
1056 var $hl_div = $('div#linktt');
1056 var $hl_div = $('div#linktt');
1057 // if we select more than 2 lines
1057 // if we select more than 2 lines
1058 if (ranges[0] != ranges[1]){
1058 if (ranges[0] != ranges[1]){
1059 if ($hl_div.length) {
1059 if ($hl_div.length) {
1060 $hl_div.html('');
1060 $hl_div.html('');
1061 } else {
1061 } else {
1062 $hl_div = $('<div id="linktt" class="hl-tip-box">');
1062 $hl_div = $('<div id="linktt" class="hl-tip-box">');
1063 $('body').prepend($hl_div);
1063 $('body').prepend($hl_div);
1064 }
1064 }
1065
1065
1066 $hl_div.append($('<a>').html(_TM['Selection link']).attr('href', location.href.substring(0, location.href.indexOf('#')) + '#L' + ranges[0] + '-'+ranges[1]));
1066 $hl_div.append($('<a>').html(_TM['Selection link']).attr('href', location.href.substring(0, location.href.indexOf('#')) + '#L' + ranges[0] + '-'+ranges[1]));
1067 xy = $(till).offset();
1067 xy = $(till).offset();
1068 $hl_div.css('top', (xy.top + yoffset) + 'px').css('left', xy.left + 'px');
1068 $hl_div.css('top', (xy.top + yoffset) + 'px').css('left', xy.left + 'px');
1069 $hl_div.show();
1069 $hl_div.show();
1070 }
1070 }
1071 else{
1071 else{
1072 $hl_div.hide();
1072 $hl_div.hide();
1073 }
1073 }
1074 }
1074 }
1075 };
1075 };
1076
1076
1077 var deleteNotification = function(url, notification_id, callbacks){
1077 var deleteNotification = function(url, notification_id, callbacks){
1078 var callback = {
1078 var callback = {
1079 success:function(o){
1079 success:function(o){
1080 $("#notification_"+notification_id).remove();
1080 $("#notification_"+notification_id).remove();
1081 _run_callbacks(callbacks);
1081 _run_callbacks(callbacks);
1082 },
1082 },
1083 failure:function(o){
1083 failure:function(o){
1084 alert("deleteNotification failure");
1084 alert("deleteNotification failure");
1085 },
1085 }
1086 };
1086 };
1087 var postData = '_method=delete';
1087 var postData = '_method=delete';
1088 var sUrl = url.replace('__NOTIFICATION_ID__',notification_id);
1088 var sUrl = url.replace('__NOTIFICATION_ID__',notification_id);
1089 var request = YAHOO.util.Connect.asyncRequest('POST', sUrl,
1089 var request = YAHOO.util.Connect.asyncRequest('POST', sUrl,
1090 callback, postData);
1090 callback, postData);
1091 };
1091 };
1092
1092
1093 var readNotification = function(url, notification_id, callbacks){
1093 var readNotification = function(url, notification_id, callbacks){
1094 var callback = {
1094 var callback = {
1095 success:function(o){
1095 success:function(o){
1096 var $obj = $("#notification_"+notification_id);
1096 var $obj = $("#notification_"+notification_id);
1097 $obj.removeClass('unread');
1097 $obj.removeClass('unread');
1098 $obj.find('.read-notification').remove();
1098 $obj.find('.read-notification').remove();
1099 _run_callbacks(callbacks);
1099 _run_callbacks(callbacks);
1100 },
1100 },
1101 failure:function(o){
1101 failure:function(o){
1102 alert("readNotification failure");
1102 alert("readNotification failure");
1103 },
1103 }
1104 };
1104 };
1105 var postData = '_method=put';
1105 var postData = '_method=put';
1106 var sUrl = url.replace('__NOTIFICATION_ID__',notification_id);
1106 var sUrl = url.replace('__NOTIFICATION_ID__',notification_id);
1107 var request = YAHOO.util.Connect.asyncRequest('POST', sUrl,
1107 var request = YAHOO.util.Connect.asyncRequest('POST', sUrl,
1108 callback, postData);
1108 callback, postData);
1109 };
1109 };
1110
1110
1111 /** MEMBERS AUTOCOMPLETE WIDGET **/
1111 /** MEMBERS AUTOCOMPLETE WIDGET **/
1112
1112
1113 var _MembersAutoComplete = function (divid, cont, users_list, groups_list) {
1113 var _MembersAutoComplete = function (divid, cont, users_list, groups_list) {
1114 var myUsers = users_list;
1114 var myUsers = users_list;
1115 var myGroups = groups_list;
1115 var myGroups = groups_list;
1116
1116
1117 // Define a custom search function for the DataSource of users
1117 // Define a custom search function for the DataSource of users
1118 var matchUsers = function (sQuery) {
1118 var matchUsers = function (sQuery) {
1119 // Case insensitive matching
1119 // Case insensitive matching
1120 var query = sQuery.toLowerCase();
1120 var query = sQuery.toLowerCase();
1121 var i = 0;
1121 var i = 0;
1122 var l = myUsers.length;
1122 var l = myUsers.length;
1123 var matches = [];
1123 var matches = [];
1124
1124
1125 // Match against each name of each contact
1125 // Match against each name of each contact
1126 for (; i < l; i++) {
1126 for (; i < l; i++) {
1127 contact = myUsers[i];
1127 contact = myUsers[i];
1128 if (((contact.fname+"").toLowerCase().indexOf(query) > -1) ||
1128 if (((contact.fname+"").toLowerCase().indexOf(query) > -1) ||
1129 ((contact.lname+"").toLowerCase().indexOf(query) > -1) ||
1129 ((contact.lname+"").toLowerCase().indexOf(query) > -1) ||
1130 ((contact.nname) && ((contact.nname).toLowerCase().indexOf(query) > -1))) {
1130 ((contact.nname) && ((contact.nname).toLowerCase().indexOf(query) > -1))) {
1131 matches[matches.length] = contact;
1131 matches[matches.length] = contact;
1132 }
1132 }
1133 }
1133 }
1134 return matches;
1134 return matches;
1135 };
1135 };
1136
1136
1137 // Define a custom search function for the DataSource of userGroups
1137 // Define a custom search function for the DataSource of userGroups
1138 var matchGroups = function (sQuery) {
1138 var matchGroups = function (sQuery) {
1139 // Case insensitive matching
1139 // Case insensitive matching
1140 var query = sQuery.toLowerCase();
1140 var query = sQuery.toLowerCase();
1141 var i = 0;
1141 var i = 0;
1142 var l = myGroups.length;
1142 var l = myGroups.length;
1143 var matches = [];
1143 var matches = [];
1144
1144
1145 // Match against each name of each contact
1145 // Match against each name of each contact
1146 for (; i < l; i++) {
1146 for (; i < l; i++) {
1147 matched_group = myGroups[i];
1147 matched_group = myGroups[i];
1148 if (matched_group.grname.toLowerCase().indexOf(query) > -1) {
1148 if (matched_group.grname.toLowerCase().indexOf(query) > -1) {
1149 matches[matches.length] = matched_group;
1149 matches[matches.length] = matched_group;
1150 }
1150 }
1151 }
1151 }
1152 return matches;
1152 return matches;
1153 };
1153 };
1154
1154
1155 //match all
1155 //match all
1156 var matchAll = function (sQuery) {
1156 var matchAll = function (sQuery) {
1157 u = matchUsers(sQuery);
1157 u = matchUsers(sQuery);
1158 g = matchGroups(sQuery);
1158 g = matchGroups(sQuery);
1159 return u.concat(g);
1159 return u.concat(g);
1160 };
1160 };
1161
1161
1162 // DataScheme for members
1162 // DataScheme for members
1163 var memberDS = new YAHOO.util.FunctionDataSource(matchAll);
1163 var memberDS = new YAHOO.util.FunctionDataSource(matchAll);
1164 memberDS.responseSchema = {
1164 memberDS.responseSchema = {
1165 fields: ["id", "fname", "lname", "nname", "grname", "grmembers", "gravatar_lnk"]
1165 fields: ["id", "fname", "lname", "nname", "grname", "grmembers", "gravatar_lnk"]
1166 };
1166 };
1167
1167
1168 // DataScheme for owner
1168 // DataScheme for owner
1169 var ownerDS = new YAHOO.util.FunctionDataSource(matchUsers);
1169 var ownerDS = new YAHOO.util.FunctionDataSource(matchUsers);
1170 ownerDS.responseSchema = {
1170 ownerDS.responseSchema = {
1171 fields: ["id", "fname", "lname", "nname", "gravatar_lnk"]
1171 fields: ["id", "fname", "lname", "nname", "gravatar_lnk"]
1172 };
1172 };
1173
1173
1174 // Instantiate AutoComplete for perms
1174 // Instantiate AutoComplete for perms
1175 var membersAC = new YAHOO.widget.AutoComplete(divid, cont, memberDS);
1175 var membersAC = new YAHOO.widget.AutoComplete(divid, cont, memberDS);
1176 membersAC.useShadow = false;
1176 membersAC.useShadow = false;
1177 membersAC.resultTypeList = false;
1177 membersAC.resultTypeList = false;
1178 membersAC.animVert = false;
1178 membersAC.animVert = false;
1179 membersAC.animHoriz = false;
1179 membersAC.animHoriz = false;
1180 membersAC.animSpeed = 0.1;
1180 membersAC.animSpeed = 0.1;
1181
1181
1182 // Instantiate AutoComplete for owner
1182 // Instantiate AutoComplete for owner
1183 var ownerAC = new YAHOO.widget.AutoComplete("user", "owner_container", ownerDS);
1183 var ownerAC = new YAHOO.widget.AutoComplete("user", "owner_container", ownerDS);
1184 ownerAC.useShadow = false;
1184 ownerAC.useShadow = false;
1185 ownerAC.resultTypeList = false;
1185 ownerAC.resultTypeList = false;
1186 ownerAC.animVert = false;
1186 ownerAC.animVert = false;
1187 ownerAC.animHoriz = false;
1187 ownerAC.animHoriz = false;
1188 ownerAC.animSpeed = 0.1;
1188 ownerAC.animSpeed = 0.1;
1189
1189
1190 // Helper highlight function for the formatter
1190 // Helper highlight function for the formatter
1191 var highlightMatch = function (full, snippet, matchindex) {
1191 var highlightMatch = function (full, snippet, matchindex) {
1192 return full.substring(0, matchindex)
1192 return full.substring(0, matchindex)
1193 + "<span class='match'>"
1193 + "<span class='match'>"
1194 + full.substr(matchindex, snippet.length)
1194 + full.substr(matchindex, snippet.length)
1195 + "</span>" + full.substring(matchindex + snippet.length);
1195 + "</span>" + full.substring(matchindex + snippet.length);
1196 };
1196 };
1197
1197
1198 // Custom formatter to highlight the matching letters
1198 // Custom formatter to highlight the matching letters
1199 var custom_formatter = function (oResultData, sQuery, sResultMatch) {
1199 var custom_formatter = function (oResultData, sQuery, sResultMatch) {
1200 var query = sQuery.toLowerCase();
1200 var query = sQuery.toLowerCase();
1201 var _gravatar = function(res, em, group){
1201 var _gravatar = function(res, em, group){
1202 if (group !== undefined){
1202 if (group !== undefined){
1203 em = '/images/icons/group.png'
1203 em = '/images/icons/group.png'
1204 }
1204 }
1205 tmpl = '<div class="ac-container-wrap"><img class="perm-gravatar-ac" src="{0}"/>{1}</div>'
1205 tmpl = '<div class="ac-container-wrap"><img class="perm-gravatar-ac" src="{0}"/>{1}</div>'
1206 return tmpl.format(em,res)
1206 return tmpl.format(em,res)
1207 }
1207 }
1208 // group
1208 // group
1209 if (oResultData.grname != undefined) {
1209 if (oResultData.grname != undefined) {
1210 var grname = oResultData.grname;
1210 var grname = oResultData.grname;
1211 var grmembers = oResultData.grmembers;
1211 var grmembers = oResultData.grmembers;
1212 var grnameMatchIndex = grname.toLowerCase().indexOf(query);
1212 var grnameMatchIndex = grname.toLowerCase().indexOf(query);
1213 var grprefix = "{0}: ".format(_TM['Group']);
1213 var grprefix = "{0}: ".format(_TM['Group']);
1214 var grsuffix = " (" + grmembers + " )";
1214 var grsuffix = " (" + grmembers + " )";
1215 var grsuffix = " ({0} {1})".format(grmembers, _TM['members']);
1215 var grsuffix = " ({0} {1})".format(grmembers, _TM['members']);
1216
1216
1217 if (grnameMatchIndex > -1) {
1217 if (grnameMatchIndex > -1) {
1218 return _gravatar(grprefix + highlightMatch(grname, query, grnameMatchIndex) + grsuffix,null,true);
1218 return _gravatar(grprefix + highlightMatch(grname, query, grnameMatchIndex) + grsuffix,null,true);
1219 }
1219 }
1220 return _gravatar(grprefix + oResultData.grname + grsuffix, null,true);
1220 return _gravatar(grprefix + oResultData.grname + grsuffix, null,true);
1221 // Users
1221 // Users
1222 } else if (oResultData.nname != undefined) {
1222 } else if (oResultData.nname != undefined) {
1223 var fname = oResultData.fname || "";
1223 var fname = oResultData.fname || "";
1224 var lname = oResultData.lname || "";
1224 var lname = oResultData.lname || "";
1225 var nname = oResultData.nname;
1225 var nname = oResultData.nname;
1226
1226
1227 // Guard against null value
1227 // Guard against null value
1228 var fnameMatchIndex = fname.toLowerCase().indexOf(query),
1228 var fnameMatchIndex = fname.toLowerCase().indexOf(query),
1229 lnameMatchIndex = lname.toLowerCase().indexOf(query),
1229 lnameMatchIndex = lname.toLowerCase().indexOf(query),
1230 nnameMatchIndex = nname.toLowerCase().indexOf(query),
1230 nnameMatchIndex = nname.toLowerCase().indexOf(query),
1231 displayfname, displaylname, displaynname;
1231 displayfname, displaylname, displaynname;
1232
1232
1233 if (fnameMatchIndex > -1) {
1233 if (fnameMatchIndex > -1) {
1234 displayfname = highlightMatch(fname, query, fnameMatchIndex);
1234 displayfname = highlightMatch(fname, query, fnameMatchIndex);
1235 } else {
1235 } else {
1236 displayfname = fname;
1236 displayfname = fname;
1237 }
1237 }
1238
1238
1239 if (lnameMatchIndex > -1) {
1239 if (lnameMatchIndex > -1) {
1240 displaylname = highlightMatch(lname, query, lnameMatchIndex);
1240 displaylname = highlightMatch(lname, query, lnameMatchIndex);
1241 } else {
1241 } else {
1242 displaylname = lname;
1242 displaylname = lname;
1243 }
1243 }
1244
1244
1245 if (nnameMatchIndex > -1) {
1245 if (nnameMatchIndex > -1) {
1246 displaynname = "(" + highlightMatch(nname, query, nnameMatchIndex) + ")";
1246 displaynname = "(" + highlightMatch(nname, query, nnameMatchIndex) + ")";
1247 } else {
1247 } else {
1248 displaynname = nname ? "(" + nname + ")" : "";
1248 displaynname = nname ? "(" + nname + ")" : "";
1249 }
1249 }
1250
1250
1251 return _gravatar(displayfname + " " + displaylname + " " + displaynname, oResultData.gravatar_lnk);
1251 return _gravatar(displayfname + " " + displaylname + " " + displaynname, oResultData.gravatar_lnk);
1252 } else {
1252 } else {
1253 return '';
1253 return '';
1254 }
1254 }
1255 };
1255 };
1256 membersAC.formatResult = custom_formatter;
1256 membersAC.formatResult = custom_formatter;
1257 ownerAC.formatResult = custom_formatter;
1257 ownerAC.formatResult = custom_formatter;
1258
1258
1259 var myHandler = function (sType, aArgs) {
1259 var myHandler = function (sType, aArgs) {
1260 var nextId = divid.split('perm_new_member_name_')[1];
1260 var nextId = divid.split('perm_new_member_name_')[1];
1261 var myAC = aArgs[0]; // reference back to the AC instance
1261 var myAC = aArgs[0]; // reference back to the AC instance
1262 var elLI = aArgs[1]; // reference to the selected LI element
1262 var elLI = aArgs[1]; // reference to the selected LI element
1263 var oData = aArgs[2]; // object literal of selected item's result data
1263 var oData = aArgs[2]; // object literal of selected item's result data
1264 //fill the autocomplete with value
1264 //fill the autocomplete with value
1265 if (oData.nname != undefined) {
1265 if (oData.nname != undefined) {
1266 //users
1266 //users
1267 myAC.getInputEl().value = oData.nname;
1267 myAC.getInputEl().value = oData.nname;
1268 $('#perm_new_member_type_'+nextId).val('user');
1268 $('#perm_new_member_type_'+nextId).val('user');
1269 } else {
1269 } else {
1270 //groups
1270 //groups
1271 myAC.getInputEl().value = oData.grname;
1271 myAC.getInputEl().value = oData.grname;
1272 $('#perm_new_member_type_'+nextId).val('users_group');
1272 $('#perm_new_member_type_'+nextId).val('users_group');
1273 }
1273 }
1274 };
1274 };
1275
1275
1276 membersAC.itemSelectEvent.subscribe(myHandler);
1276 membersAC.itemSelectEvent.subscribe(myHandler);
1277 if(ownerAC.itemSelectEvent){
1277 if(ownerAC.itemSelectEvent){
1278 ownerAC.itemSelectEvent.subscribe(myHandler);
1278 ownerAC.itemSelectEvent.subscribe(myHandler);
1279 }
1279 }
1280
1280
1281 return {
1281 return {
1282 memberDS: memberDS,
1282 memberDS: memberDS,
1283 ownerDS: ownerDS,
1283 ownerDS: ownerDS,
1284 membersAC: membersAC,
1284 membersAC: membersAC,
1285 ownerAC: ownerAC,
1285 ownerAC: ownerAC
1286 };
1286 };
1287 }
1287 }
1288
1288
1289 var MentionsAutoComplete = function (divid, cont, users_list, groups_list) {
1289 var MentionsAutoComplete = function (divid, cont, users_list, groups_list) {
1290 var myUsers = users_list;
1290 var myUsers = users_list;
1291 var myGroups = groups_list;
1291 var myGroups = groups_list;
1292
1292
1293 // Define a custom search function for the DataSource of users
1293 // Define a custom search function for the DataSource of users
1294 var matchUsers = function (sQuery) {
1294 var matchUsers = function (sQuery) {
1295 var org_sQuery = sQuery;
1295 var org_sQuery = sQuery;
1296 if(this.mentionQuery == null){
1296 if(this.mentionQuery == null){
1297 return []
1297 return []
1298 }
1298 }
1299 sQuery = this.mentionQuery;
1299 sQuery = this.mentionQuery;
1300 // Case insensitive matching
1300 // Case insensitive matching
1301 var query = sQuery.toLowerCase();
1301 var query = sQuery.toLowerCase();
1302 var i = 0;
1302 var i = 0;
1303 var l = myUsers.length;
1303 var l = myUsers.length;
1304 var matches = [];
1304 var matches = [];
1305
1305
1306 // Match against each name of each contact
1306 // Match against each name of each contact
1307 for (; i < l; i++) {
1307 for (; i < l; i++) {
1308 contact = myUsers[i];
1308 contact = myUsers[i];
1309 if (((contact.fname+"").toLowerCase().indexOf(query) > -1) ||
1309 if (((contact.fname+"").toLowerCase().indexOf(query) > -1) ||
1310 ((contact.lname+"").toLowerCase().indexOf(query) > -1) ||
1310 ((contact.lname+"").toLowerCase().indexOf(query) > -1) ||
1311 ((contact.nname) && ((contact.nname).toLowerCase().indexOf(query) > -1))) {
1311 ((contact.nname) && ((contact.nname).toLowerCase().indexOf(query) > -1))) {
1312 matches[matches.length] = contact;
1312 matches[matches.length] = contact;
1313 }
1313 }
1314 }
1314 }
1315 return matches
1315 return matches
1316 };
1316 };
1317
1317
1318 //match all
1318 //match all
1319 var matchAll = function (sQuery) {
1319 var matchAll = function (sQuery) {
1320 u = matchUsers(sQuery);
1320 u = matchUsers(sQuery);
1321 return u
1321 return u
1322 };
1322 };
1323
1323
1324 // DataScheme for owner
1324 // DataScheme for owner
1325 var ownerDS = new YAHOO.util.FunctionDataSource(matchUsers);
1325 var ownerDS = new YAHOO.util.FunctionDataSource(matchUsers);
1326
1326
1327 ownerDS.responseSchema = {
1327 ownerDS.responseSchema = {
1328 fields: ["id", "fname", "lname", "nname", "gravatar_lnk"]
1328 fields: ["id", "fname", "lname", "nname", "gravatar_lnk"]
1329 };
1329 };
1330
1330
1331 // Instantiate AutoComplete for mentions
1331 // Instantiate AutoComplete for mentions
1332 var ownerAC = new YAHOO.widget.AutoComplete(divid, cont, ownerDS);
1332 var ownerAC = new YAHOO.widget.AutoComplete(divid, cont, ownerDS);
1333 ownerAC.useShadow = false;
1333 ownerAC.useShadow = false;
1334 ownerAC.resultTypeList = false;
1334 ownerAC.resultTypeList = false;
1335 ownerAC.suppressInputUpdate = true;
1335 ownerAC.suppressInputUpdate = true;
1336 ownerAC.animVert = false;
1336 ownerAC.animVert = false;
1337 ownerAC.animHoriz = false;
1337 ownerAC.animHoriz = false;
1338 ownerAC.animSpeed = 0.1;
1338 ownerAC.animSpeed = 0.1;
1339
1339
1340 // Helper highlight function for the formatter
1340 // Helper highlight function for the formatter
1341 var highlightMatch = function (full, snippet, matchindex) {
1341 var highlightMatch = function (full, snippet, matchindex) {
1342 return full.substring(0, matchindex)
1342 return full.substring(0, matchindex)
1343 + "<span class='match'>"
1343 + "<span class='match'>"
1344 + full.substr(matchindex, snippet.length)
1344 + full.substr(matchindex, snippet.length)
1345 + "</span>" + full.substring(matchindex + snippet.length);
1345 + "</span>" + full.substring(matchindex + snippet.length);
1346 };
1346 };
1347
1347
1348 // Custom formatter to highlight the matching letters
1348 // Custom formatter to highlight the matching letters
1349 ownerAC.formatResult = function (oResultData, sQuery, sResultMatch) {
1349 ownerAC.formatResult = function (oResultData, sQuery, sResultMatch) {
1350 var org_sQuery = sQuery;
1350 var org_sQuery = sQuery;
1351 if(this.dataSource.mentionQuery != null){
1351 if(this.dataSource.mentionQuery != null){
1352 sQuery = this.dataSource.mentionQuery;
1352 sQuery = this.dataSource.mentionQuery;
1353 }
1353 }
1354
1354
1355 var query = sQuery.toLowerCase();
1355 var query = sQuery.toLowerCase();
1356 var _gravatar = function(res, em, group){
1356 var _gravatar = function(res, em, group){
1357 if (group !== undefined){
1357 if (group !== undefined){
1358 em = '/images/icons/group.png'
1358 em = '/images/icons/group.png'
1359 }
1359 }
1360 tmpl = '<div class="ac-container-wrap"><img class="perm-gravatar-ac" src="{0}"/>{1}</div>'
1360 tmpl = '<div class="ac-container-wrap"><img class="perm-gravatar-ac" src="{0}"/>{1}</div>'
1361 return tmpl.format(em,res)
1361 return tmpl.format(em,res)
1362 }
1362 }
1363 if (oResultData.nname != undefined) {
1363 if (oResultData.nname != undefined) {
1364 var fname = oResultData.fname || "";
1364 var fname = oResultData.fname || "";
1365 var lname = oResultData.lname || "";
1365 var lname = oResultData.lname || "";
1366 var nname = oResultData.nname;
1366 var nname = oResultData.nname;
1367
1367
1368 // Guard against null value
1368 // Guard against null value
1369 var fnameMatchIndex = fname.toLowerCase().indexOf(query),
1369 var fnameMatchIndex = fname.toLowerCase().indexOf(query),
1370 lnameMatchIndex = lname.toLowerCase().indexOf(query),
1370 lnameMatchIndex = lname.toLowerCase().indexOf(query),
1371 nnameMatchIndex = nname.toLowerCase().indexOf(query),
1371 nnameMatchIndex = nname.toLowerCase().indexOf(query),
1372 displayfname, displaylname, displaynname;
1372 displayfname, displaylname, displaynname;
1373
1373
1374 if (fnameMatchIndex > -1) {
1374 if (fnameMatchIndex > -1) {
1375 displayfname = highlightMatch(fname, query, fnameMatchIndex);
1375 displayfname = highlightMatch(fname, query, fnameMatchIndex);
1376 } else {
1376 } else {
1377 displayfname = fname;
1377 displayfname = fname;
1378 }
1378 }
1379
1379
1380 if (lnameMatchIndex > -1) {
1380 if (lnameMatchIndex > -1) {
1381 displaylname = highlightMatch(lname, query, lnameMatchIndex);
1381 displaylname = highlightMatch(lname, query, lnameMatchIndex);
1382 } else {
1382 } else {
1383 displaylname = lname;
1383 displaylname = lname;
1384 }
1384 }
1385
1385
1386 if (nnameMatchIndex > -1) {
1386 if (nnameMatchIndex > -1) {
1387 displaynname = "(" + highlightMatch(nname, query, nnameMatchIndex) + ")";
1387 displaynname = "(" + highlightMatch(nname, query, nnameMatchIndex) + ")";
1388 } else {
1388 } else {
1389 displaynname = nname ? "(" + nname + ")" : "";
1389 displaynname = nname ? "(" + nname + ")" : "";
1390 }
1390 }
1391
1391
1392 return _gravatar(displayfname + " " + displaylname + " " + displaynname, oResultData.gravatar_lnk);
1392 return _gravatar(displayfname + " " + displaylname + " " + displaynname, oResultData.gravatar_lnk);
1393 } else {
1393 } else {
1394 return '';
1394 return '';
1395 }
1395 }
1396 };
1396 };
1397
1397
1398 if(ownerAC.itemSelectEvent){
1398 if(ownerAC.itemSelectEvent){
1399 ownerAC.itemSelectEvent.subscribe(function (sType, aArgs) {
1399 ownerAC.itemSelectEvent.subscribe(function (sType, aArgs) {
1400 var myAC = aArgs[0]; // reference back to the AC instance
1400 var myAC = aArgs[0]; // reference back to the AC instance
1401 var elLI = aArgs[1]; // reference to the selected LI element
1401 var elLI = aArgs[1]; // reference to the selected LI element
1402 var oData = aArgs[2]; // object literal of selected item's result data
1402 var oData = aArgs[2]; // object literal of selected item's result data
1403 //fill the autocomplete with value
1403 //fill the autocomplete with value
1404 if (oData.nname != undefined) {
1404 if (oData.nname != undefined) {
1405 //users
1405 //users
1406 //Replace the mention name with replaced
1406 //Replace the mention name with replaced
1407 var re = new RegExp();
1407 var re = new RegExp();
1408 var org = myAC.getInputEl().value;
1408 var org = myAC.getInputEl().value;
1409 var chunks = myAC.dataSource.chunks
1409 var chunks = myAC.dataSource.chunks
1410 // replace middle chunk(the search term) with actuall match
1410 // replace middle chunk(the search term) with actuall match
1411 chunks[1] = chunks[1].replace('@'+myAC.dataSource.mentionQuery,
1411 chunks[1] = chunks[1].replace('@'+myAC.dataSource.mentionQuery,
1412 '@'+oData.nname+' ');
1412 '@'+oData.nname+' ');
1413 myAC.getInputEl().value = chunks.join('')
1413 myAC.getInputEl().value = chunks.join('')
1414 myAC.getInputEl().focus(); // Y U NO WORK !?
1414 myAC.getInputEl().focus(); // Y U NO WORK !?
1415 } else {
1415 } else {
1416 //groups
1416 //groups
1417 myAC.getInputEl().value = oData.grname;
1417 myAC.getInputEl().value = oData.grname;
1418 $('#perm_new_member_type').val('users_group');
1418 $('#perm_new_member_type').val('users_group');
1419 }
1419 }
1420 });
1420 });
1421 }
1421 }
1422
1422
1423 // in this keybuffer we will gather current value of search !
1423 // in this keybuffer we will gather current value of search !
1424 // since we need to get this just when someone does `@` then we do the
1424 // since we need to get this just when someone does `@` then we do the
1425 // search
1425 // search
1426 ownerAC.dataSource.chunks = [];
1426 ownerAC.dataSource.chunks = [];
1427 ownerAC.dataSource.mentionQuery = null;
1427 ownerAC.dataSource.mentionQuery = null;
1428
1428
1429 ownerAC.get_mention = function(msg, max_pos) {
1429 ownerAC.get_mention = function(msg, max_pos) {
1430 var org = msg;
1430 var org = msg;
1431 // Must match utils2.py MENTIONS_REGEX.
1431 // Must match utils2.py MENTIONS_REGEX.
1432 // Only matching on string up to cursor, so it must end with $
1432 // Only matching on string up to cursor, so it must end with $
1433 var re = new RegExp('(?:^|[^a-zA-Z0-9])@([a-zA-Z0-9][-_.a-zA-Z0-9]*[a-zA-Z0-9])$')
1433 var re = new RegExp('(?:^|[^a-zA-Z0-9])@([a-zA-Z0-9][-_.a-zA-Z0-9]*[a-zA-Z0-9])$')
1434 var chunks = [];
1434 var chunks = [];
1435
1435
1436 // cut first chunk until current pos
1436 // cut first chunk until current pos
1437 var to_max = msg.substr(0, max_pos);
1437 var to_max = msg.substr(0, max_pos);
1438 var at_pos = Math.max(0,to_max.lastIndexOf('@')-1);
1438 var at_pos = Math.max(0,to_max.lastIndexOf('@')-1);
1439 var msg2 = to_max.substr(at_pos);
1439 var msg2 = to_max.substr(at_pos);
1440
1440
1441 chunks.push(org.substr(0,at_pos))// prefix chunk
1441 chunks.push(org.substr(0,at_pos))// prefix chunk
1442 chunks.push(msg2) // search chunk
1442 chunks.push(msg2) // search chunk
1443 chunks.push(org.substr(max_pos)) // postfix chunk
1443 chunks.push(org.substr(max_pos)) // postfix chunk
1444
1444
1445 // clean up msg2 for filtering and regex match
1445 // clean up msg2 for filtering and regex match
1446 var msg2 = msg2.lstrip(' ').lstrip('\n');
1446 var msg2 = msg2.lstrip(' ').lstrip('\n');
1447
1447
1448 if(re.test(msg2)){
1448 if(re.test(msg2)){
1449 var unam = re.exec(msg2)[1];
1449 var unam = re.exec(msg2)[1];
1450 return [unam, chunks];
1450 return [unam, chunks];
1451 }
1451 }
1452 return [null, null];
1452 return [null, null];
1453 };
1453 };
1454
1454
1455 $divid = $('#'+divid);
1455 $divid = $('#'+divid);
1456 $divid.keyup(function(e){
1456 $divid.keyup(function(e){
1457 var currentMessage = $divid.val();
1457 var currentMessage = $divid.val();
1458 var currentCaretPosition = $divid[0].selectionStart;
1458 var currentCaretPosition = $divid[0].selectionStart;
1459
1459
1460 var unam = ownerAC.get_mention(currentMessage, currentCaretPosition);
1460 var unam = ownerAC.get_mention(currentMessage, currentCaretPosition);
1461 var curr_search = null;
1461 var curr_search = null;
1462 if(unam[0]){
1462 if(unam[0]){
1463 curr_search = unam[0];
1463 curr_search = unam[0];
1464 }
1464 }
1465
1465
1466 ownerAC.dataSource.chunks = unam[1];
1466 ownerAC.dataSource.chunks = unam[1];
1467 ownerAC.dataSource.mentionQuery = curr_search;
1467 ownerAC.dataSource.mentionQuery = curr_search;
1468 });
1468 });
1469 }
1469 }
1470
1470
1471 var addReviewMember = function(id,fname,lname,nname,gravatar_link){
1471 var addReviewMember = function(id,fname,lname,nname,gravatar_link){
1472 var displayname = "{0} {1} ({2})".format(fname, lname, nname);
1472 var displayname = "{0} {1} ({2})".format(fname, lname, nname);
1473 var element = (
1473 var element = (
1474 ' <li id="reviewer_{2}">\n'+
1474 ' <li id="reviewer_{2}">\n'+
1475 ' <div class="reviewers_member">\n'+
1475 ' <div class="reviewers_member">\n'+
1476 ' <div class="reviewer_status tooltip" title="not_reviewed">\n'+
1476 ' <div class="reviewer_status tooltip" title="not_reviewed">\n'+
1477 ' <img src="/images/icons/flag_status_not_reviewed.png"/>\n'+
1477 ' <img src="/images/icons/flag_status_not_reviewed.png"/>\n'+
1478 ' </div>\n'+
1478 ' </div>\n'+
1479 ' <div class="reviewer_gravatar gravatar"><img alt="gravatar" src="{0}"/> </div>\n'+
1479 ' <div class="reviewer_gravatar gravatar"><img alt="gravatar" src="{0}"/> </div>\n'+
1480 ' <div style="float:left;">{1}</div>\n'+
1480 ' <div style="float:left;">{1}</div>\n'+
1481 ' <input type="hidden" value="{2}" name="review_members" />\n'+
1481 ' <input type="hidden" value="{2}" name="review_members" />\n'+
1482 ' <div class="reviewer_member_remove action_button" onclick="removeReviewMember({2})">\n'+
1482 ' <div class="reviewer_member_remove action_button" onclick="removeReviewMember({2})">\n'+
1483 ' <i class="icon-remove-sign" style="color: #FF4444;"></i>\n'+
1483 ' <i class="icon-remove-sign" style="color: #FF4444;"></i>\n'+
1484 ' </div> *\n'+
1484 ' </div> *\n'+
1485 ' </div>\n'+
1485 ' </div>\n'+
1486 ' </li>\n'
1486 ' </li>\n'
1487 ).format(gravatar_link, displayname, id);
1487 ).format(gravatar_link, displayname, id);
1488 // check if we don't have this ID already in
1488 // check if we don't have this ID already in
1489 var ids = [];
1489 var ids = [];
1490 $('#review_members').find('li').each(function() {
1490 $('#review_members').find('li').each(function() {
1491 ids.push(this.id);
1491 ids.push(this.id);
1492 });
1492 });
1493 if(ids.indexOf('reviewer_'+id) == -1){
1493 if(ids.indexOf('reviewer_'+id) == -1){
1494 //only add if it's not there
1494 //only add if it's not there
1495 $('#review_members').append(element);
1495 $('#review_members').append(element);
1496 }
1496 }
1497 }
1497 }
1498
1498
1499 var removeReviewMember = function(reviewer_id, repo_name, pull_request_id){
1499 var removeReviewMember = function(reviewer_id, repo_name, pull_request_id){
1500 var $li = $('#reviewer_{0}'.format(reviewer_id));
1500 var $li = $('#reviewer_{0}'.format(reviewer_id));
1501 $li.find('div div').css("text-decoration", "line-through");
1501 $li.find('div div').css("text-decoration", "line-through");
1502 $li.find('input').remove();
1502 $li.find('input').remove();
1503 $li.find('.reviewer_member_remove').remove();
1503 $li.find('.reviewer_member_remove').remove();
1504 }
1504 }
1505
1505
1506 /* handle "Save Changes" of addReviewMember and removeReviewMember on PR */
1506 /* handle "Save Changes" of addReviewMember and removeReviewMember on PR */
1507 var updateReviewers = function(reviewers_ids, repo_name, pull_request_id){
1507 var updateReviewers = function(reviewers_ids, repo_name, pull_request_id){
1508 if (reviewers_ids === undefined){
1508 if (reviewers_ids === undefined){
1509 var reviewers_ids = [];
1509 var reviewers_ids = [];
1510 $('#review_members').find('input').each(function(){
1510 $('#review_members').find('input').each(function(){
1511 reviewers_ids.push(this.value);
1511 reviewers_ids.push(this.value);
1512 });
1512 });
1513 }
1513 }
1514 var url = pyroutes.url('pullrequest_update', {"repo_name":repo_name,
1514 var url = pyroutes.url('pullrequest_update', {"repo_name":repo_name,
1515 "pull_request_id": pull_request_id});
1515 "pull_request_id": pull_request_id});
1516 var postData = {'_method':'put',
1516 var postData = {'_method':'put',
1517 'reviewers_ids': reviewers_ids};
1517 'reviewers_ids': reviewers_ids};
1518 var success = function(o){
1518 var success = function(o){
1519 window.location.reload();
1519 window.location.reload();
1520 }
1520 }
1521 ajaxPOST(url,postData,success);
1521 ajaxPOST(url,postData,success);
1522 }
1522 }
1523
1523
1524 /* activate auto completion of users and groups ... but only used for users as PR reviewers */
1524 /* activate auto completion of users and groups ... but only used for users as PR reviewers */
1525 var PullRequestAutoComplete = function (divid, cont, users_list, groups_list) {
1525 var PullRequestAutoComplete = function (divid, cont, users_list, groups_list) {
1526 var myUsers = users_list;
1526 var myUsers = users_list;
1527 var myGroups = groups_list;
1527 var myGroups = groups_list;
1528
1528
1529 // Define a custom search function for the DataSource of users
1529 // Define a custom search function for the DataSource of users
1530 var matchUsers = function (sQuery) {
1530 var matchUsers = function (sQuery) {
1531 // Case insensitive matching
1531 // Case insensitive matching
1532 var query = sQuery.toLowerCase();
1532 var query = sQuery.toLowerCase();
1533 var i = 0;
1533 var i = 0;
1534 var l = myUsers.length;
1534 var l = myUsers.length;
1535 var matches = [];
1535 var matches = [];
1536
1536
1537 // Match against each name of each contact
1537 // Match against each name of each contact
1538 for (; i < l; i++) {
1538 for (; i < l; i++) {
1539 contact = myUsers[i];
1539 contact = myUsers[i];
1540 if (((contact.fname+"").toLowerCase().indexOf(query) > -1) ||
1540 if (((contact.fname+"").toLowerCase().indexOf(query) > -1) ||
1541 ((contact.lname+"").toLowerCase().indexOf(query) > -1) ||
1541 ((contact.lname+"").toLowerCase().indexOf(query) > -1) ||
1542 ((contact.nname) && ((contact.nname).toLowerCase().indexOf(query) > -1))) {
1542 ((contact.nname) && ((contact.nname).toLowerCase().indexOf(query) > -1))) {
1543 matches[matches.length] = contact;
1543 matches[matches.length] = contact;
1544 }
1544 }
1545 }
1545 }
1546 return matches;
1546 return matches;
1547 };
1547 };
1548
1548
1549 // Define a custom search function for the DataSource of userGroups
1549 // Define a custom search function for the DataSource of userGroups
1550 var matchGroups = function (sQuery) {
1550 var matchGroups = function (sQuery) {
1551 // Case insensitive matching
1551 // Case insensitive matching
1552 var query = sQuery.toLowerCase();
1552 var query = sQuery.toLowerCase();
1553 var i = 0;
1553 var i = 0;
1554 var l = myGroups.length;
1554 var l = myGroups.length;
1555 var matches = [];
1555 var matches = [];
1556
1556
1557 // Match against each name of each contact
1557 // Match against each name of each contact
1558 for (; i < l; i++) {
1558 for (; i < l; i++) {
1559 matched_group = myGroups[i];
1559 matched_group = myGroups[i];
1560 if (matched_group.grname.toLowerCase().indexOf(query) > -1) {
1560 if (matched_group.grname.toLowerCase().indexOf(query) > -1) {
1561 matches[matches.length] = matched_group;
1561 matches[matches.length] = matched_group;
1562 }
1562 }
1563 }
1563 }
1564 return matches;
1564 return matches;
1565 };
1565 };
1566
1566
1567 //match all
1567 //match all
1568 var matchAll = function (sQuery) {
1568 var matchAll = function (sQuery) {
1569 u = matchUsers(sQuery);
1569 u = matchUsers(sQuery);
1570 return u
1570 return u
1571 };
1571 };
1572
1572
1573 // DataScheme for owner
1573 // DataScheme for owner
1574 var ownerDS = new YAHOO.util.FunctionDataSource(matchUsers);
1574 var ownerDS = new YAHOO.util.FunctionDataSource(matchUsers);
1575
1575
1576 ownerDS.responseSchema = {
1576 ownerDS.responseSchema = {
1577 fields: ["id", "fname", "lname", "nname", "gravatar_lnk"]
1577 fields: ["id", "fname", "lname", "nname", "gravatar_lnk"]
1578 };
1578 };
1579
1579
1580 // Instantiate AutoComplete for mentions
1580 // Instantiate AutoComplete for mentions
1581 var reviewerAC = new YAHOO.widget.AutoComplete(divid, cont, ownerDS);
1581 var reviewerAC = new YAHOO.widget.AutoComplete(divid, cont, ownerDS);
1582 reviewerAC.useShadow = false;
1582 reviewerAC.useShadow = false;
1583 reviewerAC.resultTypeList = false;
1583 reviewerAC.resultTypeList = false;
1584 reviewerAC.suppressInputUpdate = true;
1584 reviewerAC.suppressInputUpdate = true;
1585 reviewerAC.animVert = false;
1585 reviewerAC.animVert = false;
1586 reviewerAC.animHoriz = false;
1586 reviewerAC.animHoriz = false;
1587 reviewerAC.animSpeed = 0.1;
1587 reviewerAC.animSpeed = 0.1;
1588
1588
1589 // Helper highlight function for the formatter
1589 // Helper highlight function for the formatter
1590 var highlightMatch = function (full, snippet, matchindex) {
1590 var highlightMatch = function (full, snippet, matchindex) {
1591 return full.substring(0, matchindex)
1591 return full.substring(0, matchindex)
1592 + "<span class='match'>"
1592 + "<span class='match'>"
1593 + full.substr(matchindex, snippet.length)
1593 + full.substr(matchindex, snippet.length)
1594 + "</span>" + full.substring(matchindex + snippet.length);
1594 + "</span>" + full.substring(matchindex + snippet.length);
1595 };
1595 };
1596
1596
1597 // Custom formatter to highlight the matching letters
1597 // Custom formatter to highlight the matching letters
1598 reviewerAC.formatResult = function (oResultData, sQuery, sResultMatch) {
1598 reviewerAC.formatResult = function (oResultData, sQuery, sResultMatch) {
1599 var org_sQuery = sQuery;
1599 var org_sQuery = sQuery;
1600 if(this.dataSource.mentionQuery != null){
1600 if(this.dataSource.mentionQuery != null){
1601 sQuery = this.dataSource.mentionQuery;
1601 sQuery = this.dataSource.mentionQuery;
1602 }
1602 }
1603
1603
1604 var query = sQuery.toLowerCase();
1604 var query = sQuery.toLowerCase();
1605 var _gravatar = function(res, em, group){
1605 var _gravatar = function(res, em, group){
1606 if (group !== undefined){
1606 if (group !== undefined){
1607 em = '/images/icons/group.png'
1607 em = '/images/icons/group.png'
1608 }
1608 }
1609 tmpl = '<div class="ac-container-wrap"><img class="perm-gravatar-ac" src="{0}"/>{1}</div>'
1609 tmpl = '<div class="ac-container-wrap"><img class="perm-gravatar-ac" src="{0}"/>{1}</div>'
1610 return tmpl.format(em,res)
1610 return tmpl.format(em,res)
1611 }
1611 }
1612 if (oResultData.nname != undefined) {
1612 if (oResultData.nname != undefined) {
1613 var fname = oResultData.fname || "";
1613 var fname = oResultData.fname || "";
1614 var lname = oResultData.lname || "";
1614 var lname = oResultData.lname || "";
1615 var nname = oResultData.nname;
1615 var nname = oResultData.nname;
1616
1616
1617 // Guard against null value
1617 // Guard against null value
1618 var fnameMatchIndex = fname.toLowerCase().indexOf(query),
1618 var fnameMatchIndex = fname.toLowerCase().indexOf(query),
1619 lnameMatchIndex = lname.toLowerCase().indexOf(query),
1619 lnameMatchIndex = lname.toLowerCase().indexOf(query),
1620 nnameMatchIndex = nname.toLowerCase().indexOf(query),
1620 nnameMatchIndex = nname.toLowerCase().indexOf(query),
1621 displayfname, displaylname, displaynname;
1621 displayfname, displaylname, displaynname;
1622
1622
1623 if (fnameMatchIndex > -1) {
1623 if (fnameMatchIndex > -1) {
1624 displayfname = highlightMatch(fname, query, fnameMatchIndex);
1624 displayfname = highlightMatch(fname, query, fnameMatchIndex);
1625 } else {
1625 } else {
1626 displayfname = fname;
1626 displayfname = fname;
1627 }
1627 }
1628
1628
1629 if (lnameMatchIndex > -1) {
1629 if (lnameMatchIndex > -1) {
1630 displaylname = highlightMatch(lname, query, lnameMatchIndex);
1630 displaylname = highlightMatch(lname, query, lnameMatchIndex);
1631 } else {
1631 } else {
1632 displaylname = lname;
1632 displaylname = lname;
1633 }
1633 }
1634
1634
1635 if (nnameMatchIndex > -1) {
1635 if (nnameMatchIndex > -1) {
1636 displaynname = "(" + highlightMatch(nname, query, nnameMatchIndex) + ")";
1636 displaynname = "(" + highlightMatch(nname, query, nnameMatchIndex) + ")";
1637 } else {
1637 } else {
1638 displaynname = nname ? "(" + nname + ")" : "";
1638 displaynname = nname ? "(" + nname + ")" : "";
1639 }
1639 }
1640
1640
1641 return _gravatar(displayfname + " " + displaylname + " " + displaynname, oResultData.gravatar_lnk);
1641 return _gravatar(displayfname + " " + displaylname + " " + displaynname, oResultData.gravatar_lnk);
1642 } else {
1642 } else {
1643 return '';
1643 return '';
1644 }
1644 }
1645 };
1645 };
1646
1646
1647 //members cache to catch duplicates
1647 //members cache to catch duplicates
1648 reviewerAC.dataSource.cache = [];
1648 reviewerAC.dataSource.cache = [];
1649 // hack into select event
1649 // hack into select event
1650 if(reviewerAC.itemSelectEvent){
1650 if(reviewerAC.itemSelectEvent){
1651 reviewerAC.itemSelectEvent.subscribe(function (sType, aArgs) {
1651 reviewerAC.itemSelectEvent.subscribe(function (sType, aArgs) {
1652
1652
1653 var myAC = aArgs[0]; // reference back to the AC instance
1653 var myAC = aArgs[0]; // reference back to the AC instance
1654 var elLI = aArgs[1]; // reference to the selected LI element
1654 var elLI = aArgs[1]; // reference to the selected LI element
1655 var oData = aArgs[2]; // object literal of selected item's result data
1655 var oData = aArgs[2]; // object literal of selected item's result data
1656
1656
1657 //fill the autocomplete with value
1657 //fill the autocomplete with value
1658 if (oData.nname != undefined) {
1658 if (oData.nname != undefined) {
1659 addReviewMember(oData.id, oData.fname, oData.lname, oData.nname,
1659 addReviewMember(oData.id, oData.fname, oData.lname, oData.nname,
1660 oData.gravatar_lnk);
1660 oData.gravatar_lnk);
1661 myAC.dataSource.cache.push(oData.id);
1661 myAC.dataSource.cache.push(oData.id);
1662 $('#user').val('');
1662 $('#user').val('');
1663 }
1663 }
1664 });
1664 });
1665 }
1665 }
1666 }
1666 }
1667
1667
1668 /**
1668 /**
1669 * Activate .quick_repo_menu
1669 * Activate .quick_repo_menu
1670 */
1670 */
1671 var quick_repo_menu = function(){
1671 var quick_repo_menu = function(){
1672 $(".quick_repo_menu").mouseenter(function(e) {
1672 $(".quick_repo_menu").mouseenter(function(e) {
1673 var $menu = $(e.currentTarget).children().first().children().first();
1673 var $menu = $(e.currentTarget).children().first().children().first();
1674 if($menu.hasClass('hidden')){
1674 if($menu.hasClass('hidden')){
1675 $menu.removeClass('hidden').addClass('active');
1675 $menu.removeClass('hidden').addClass('active');
1676 $(e.currentTarget).removeClass('hidden').addClass('active');
1676 $(e.currentTarget).removeClass('hidden').addClass('active');
1677 }
1677 }
1678 })
1678 })
1679 $(".quick_repo_menu").mouseleave(function(e) {
1679 $(".quick_repo_menu").mouseleave(function(e) {
1680 var $menu = $(e.currentTarget).children().first().children().first();
1680 var $menu = $(e.currentTarget).children().first().children().first();
1681 if($menu.hasClass('active')){
1681 if($menu.hasClass('active')){
1682 $menu.removeClass('active').addClass('hidden');
1682 $menu.removeClass('active').addClass('hidden');
1683 $(e.currentTarget).removeClass('active').addClass('hidden');
1683 $(e.currentTarget).removeClass('active').addClass('hidden');
1684 }
1684 }
1685 })
1685 })
1686 };
1686 };
1687
1687
1688
1688
1689 /**
1689 /**
1690 * TABLE SORTING
1690 * TABLE SORTING
1691 */
1691 */
1692
1692
1693 var revisionSort = function(a, b, desc, field) {
1693 var revisionSort = function(a, b, desc, field) {
1694 var a_ = parseInt(a.getData('last_rev_raw') || 0);
1694 var a_ = parseInt(a.getData('last_rev_raw') || 0);
1695 var b_ = parseInt(b.getData('last_rev_raw') || 0);
1695 var b_ = parseInt(b.getData('last_rev_raw') || 0);
1696
1696
1697 return YAHOO.util.Sort.compare(a_, b_, desc);
1697 return YAHOO.util.Sort.compare(a_, b_, desc);
1698 };
1698 };
1699
1699
1700 var ageSort = function(a, b, desc, field) {
1700 var ageSort = function(a, b, desc, field) {
1701 // data is like: <span class="tooltip" date="2014-06-04 18:18:55.325474" title="Wed, 04 Jun 2014 18:18:55">1 day and 23 hours ago</span>
1701 // data is like: <span class="tooltip" date="2014-06-04 18:18:55.325474" title="Wed, 04 Jun 2014 18:18:55">1 day and 23 hours ago</span>
1702 var a_ = $(a.getData(field)).attr('date');
1702 var a_ = $(a.getData(field)).attr('date');
1703 var b_ = $(b.getData(field)).attr('date');
1703 var b_ = $(b.getData(field)).attr('date');
1704
1704
1705 return YAHOO.util.Sort.compare(a_, b_, desc);
1705 return YAHOO.util.Sort.compare(a_, b_, desc);
1706 };
1706 };
1707
1707
1708 var lastLoginSort = function(a, b, desc, field) {
1708 var lastLoginSort = function(a, b, desc, field) {
1709 var a_ = parseFloat(a.getData('last_login_raw') || 0);
1709 var a_ = parseFloat(a.getData('last_login_raw') || 0);
1710 var b_ = parseFloat(b.getData('last_login_raw') || 0);
1710 var b_ = parseFloat(b.getData('last_login_raw') || 0);
1711
1711
1712 return YAHOO.util.Sort.compare(a_, b_, desc);
1712 return YAHOO.util.Sort.compare(a_, b_, desc);
1713 };
1713 };
1714
1714
1715 var nameSort = function(a, b, desc, field) {
1715 var nameSort = function(a, b, desc, field) {
1716 var a_ = a.getData('raw_name') || 0;
1716 var a_ = a.getData('raw_name') || 0;
1717 var b_ = b.getData('raw_name') || 0;
1717 var b_ = b.getData('raw_name') || 0;
1718
1718
1719 return YAHOO.util.Sort.compare(a_, b_, desc);
1719 return YAHOO.util.Sort.compare(a_, b_, desc);
1720 };
1720 };
1721
1721
1722 var dateSort = function(a, b, desc, field) {
1722 var dateSort = function(a, b, desc, field) {
1723 var a_ = parseFloat(a.getData('raw_date') || 0);
1723 var a_ = parseFloat(a.getData('raw_date') || 0);
1724 var b_ = parseFloat(b.getData('raw_date') || 0);
1724 var b_ = parseFloat(b.getData('raw_date') || 0);
1725
1725
1726 return YAHOO.util.Sort.compare(a_, b_, desc);
1726 return YAHOO.util.Sort.compare(a_, b_, desc);
1727 };
1727 };
1728
1728
1729 var addPermAction = function(_html, users_list, groups_list){
1729 var addPermAction = function(_html, users_list, groups_list){
1730 var $last_node = $('.last_new_member').last(); // empty tr between last and add
1730 var $last_node = $('.last_new_member').last(); // empty tr between last and add
1731 var next_id = $('.new_members').length;
1731 var next_id = $('.new_members').length;
1732 $last_node.before($('<tr class="new_members">').append(_html.format(next_id)));
1732 $last_node.before($('<tr class="new_members">').append(_html.format(next_id)));
1733 _MembersAutoComplete("perm_new_member_name_"+next_id,
1733 _MembersAutoComplete("perm_new_member_name_"+next_id,
1734 "perm_container_"+next_id, users_list, groups_list);
1734 "perm_container_"+next_id, users_list, groups_list);
1735 }
1735 }
1736
1736
1737 function ajaxActionRevokePermission(url, obj_id, obj_type, field_id, extra_data) {
1737 function ajaxActionRevokePermission(url, obj_id, obj_type, field_id, extra_data) {
1738 var callback = {
1738 var callback = {
1739 success: function (o) {
1739 success: function (o) {
1740 $('#' + field_id).remove();
1740 $('#' + field_id).remove();
1741 },
1741 },
1742 failure: function (o) {
1742 failure: function (o) {
1743 alert(_TM['Failed to revoke permission'] + ": " + o.status);
1743 alert(_TM['Failed to revoke permission'] + ": " + o.status);
1744 },
1744 }
1745 };
1745 };
1746 query_params = {
1746 query_params = {
1747 '_method': 'delete'
1747 '_method': 'delete'
1748 }
1748 }
1749 // put extra data into POST
1749 // put extra data into POST
1750 if (extra_data !== undefined && (typeof extra_data === 'object')){
1750 if (extra_data !== undefined && (typeof extra_data === 'object')){
1751 for(k in extra_data){
1751 for(k in extra_data){
1752 query_params[k] = extra_data[k];
1752 query_params[k] = extra_data[k];
1753 }
1753 }
1754 }
1754 }
1755
1755
1756 if (obj_type=='user'){
1756 if (obj_type=='user'){
1757 query_params['user_id'] = obj_id;
1757 query_params['user_id'] = obj_id;
1758 query_params['obj_type'] = 'user';
1758 query_params['obj_type'] = 'user';
1759 }
1759 }
1760 else if (obj_type=='user_group'){
1760 else if (obj_type=='user_group'){
1761 query_params['user_group_id'] = obj_id;
1761 query_params['user_group_id'] = obj_id;
1762 query_params['obj_type'] = 'user_group';
1762 query_params['obj_type'] = 'user_group';
1763 }
1763 }
1764
1764
1765 var request = YAHOO.util.Connect.asyncRequest('POST', url, callback,
1765 var request = YAHOO.util.Connect.asyncRequest('POST', url, callback,
1766 _toQueryString(query_params));
1766 _toQueryString(query_params));
1767 };
1767 };
1768
1768
1769 /* Multi selectors */
1769 /* Multi selectors */
1770
1770
1771 var MultiSelectWidget = function(selected_id, available_id, form_id){
1771 var MultiSelectWidget = function(selected_id, available_id, form_id){
1772 var $availableselect = $('#' + available_id);
1772 var $availableselect = $('#' + available_id);
1773 var $selectedselect = $('#' + selected_id);
1773 var $selectedselect = $('#' + selected_id);
1774
1774
1775 //fill available only with those not in selected
1775 //fill available only with those not in selected
1776 var $selectedoptions = $selectedselect.children('option');
1776 var $selectedoptions = $selectedselect.children('option');
1777 $availableselect.children('option').filter(function(i, e){
1777 $availableselect.children('option').filter(function(i, e){
1778 for(var j = 0, node; node = $selectedoptions[j]; j++){
1778 for(var j = 0, node; node = $selectedoptions[j]; j++){
1779 if(node.value == e.value){
1779 if(node.value == e.value){
1780 return true;
1780 return true;
1781 }
1781 }
1782 }
1782 }
1783 return false;
1783 return false;
1784 }).remove();
1784 }).remove();
1785
1785
1786 $('#add_element').click(function(e){
1786 $('#add_element').click(function(e){
1787 $selectedselect.append($availableselect.children('option:selected'));
1787 $selectedselect.append($availableselect.children('option:selected'));
1788 });
1788 });
1789 $('#remove_element').click(function(e){
1789 $('#remove_element').click(function(e){
1790 $availableselect.append($selectedselect.children('option:selected'));
1790 $availableselect.append($selectedselect.children('option:selected'));
1791 });
1791 });
1792 $('#add_all_elements').click(function(e){
1792 $('#add_all_elements').click(function(e){
1793 $selectedselect.append($availableselect.children('option'));
1793 $selectedselect.append($availableselect.children('option'));
1794 });
1794 });
1795 $('#remove_all_elements').click(function(e){
1795 $('#remove_all_elements').click(function(e){
1796 $availableselect.append($selectedselect.children('option'));
1796 $availableselect.append($selectedselect.children('option'));
1797 });
1797 });
1798
1798
1799 $('#'+form_id).submit(function(){
1799 $('#'+form_id).submit(function(){
1800 $selectedselect.children('option').each(function(i, e){
1800 $selectedselect.children('option').each(function(i, e){
1801 e.selected = 'selected';
1801 e.selected = 'selected';
1802 });
1802 });
1803 });
1803 });
1804 }
1804 }
1805
1805
1806 // custom paginator
1806 // custom paginator
1807 var YUI_paginator = function(links_per_page, containers){
1807 var YUI_paginator = function(links_per_page, containers){
1808
1808
1809 (function () {
1809 (function () {
1810
1810
1811 var Paginator = YAHOO.widget.Paginator,
1811 var Paginator = YAHOO.widget.Paginator,
1812 l = YAHOO.lang,
1812 l = YAHOO.lang,
1813 setId = YAHOO.util.Dom.generateId;
1813 setId = YAHOO.util.Dom.generateId;
1814
1814
1815 Paginator.ui.MyFirstPageLink = function (p) {
1815 Paginator.ui.MyFirstPageLink = function (p) {
1816 this.paginator = p;
1816 this.paginator = p;
1817
1817
1818 p.subscribe('recordOffsetChange',this.update,this,true);
1818 p.subscribe('recordOffsetChange',this.update,this,true);
1819 p.subscribe('rowsPerPageChange',this.update,this,true);
1819 p.subscribe('rowsPerPageChange',this.update,this,true);
1820 p.subscribe('totalRecordsChange',this.update,this,true);
1820 p.subscribe('totalRecordsChange',this.update,this,true);
1821 p.subscribe('destroy',this.destroy,this,true);
1821 p.subscribe('destroy',this.destroy,this,true);
1822
1822
1823 // TODO: make this work
1823 // TODO: make this work
1824 p.subscribe('firstPageLinkLabelChange',this.update,this,true);
1824 p.subscribe('firstPageLinkLabelChange',this.update,this,true);
1825 p.subscribe('firstPageLinkClassChange',this.update,this,true);
1825 p.subscribe('firstPageLinkClassChange',this.update,this,true);
1826 };
1826 };
1827
1827
1828 Paginator.ui.MyFirstPageLink.init = function (p) {
1828 Paginator.ui.MyFirstPageLink.init = function (p) {
1829 p.setAttributeConfig('firstPageLinkLabel', {
1829 p.setAttributeConfig('firstPageLinkLabel', {
1830 value : 1,
1830 value : 1,
1831 validator : l.isString
1831 validator : l.isString
1832 });
1832 });
1833 p.setAttributeConfig('firstPageLinkClass', {
1833 p.setAttributeConfig('firstPageLinkClass', {
1834 value : 'yui-pg-first',
1834 value : 'yui-pg-first',
1835 validator : l.isString
1835 validator : l.isString
1836 });
1836 });
1837 p.setAttributeConfig('firstPageLinkTitle', {
1837 p.setAttributeConfig('firstPageLinkTitle', {
1838 value : 'First Page',
1838 value : 'First Page',
1839 validator : l.isString
1839 validator : l.isString
1840 });
1840 });
1841 };
1841 };
1842
1842
1843 // Instance members and methods
1843 // Instance members and methods
1844 Paginator.ui.MyFirstPageLink.prototype = {
1844 Paginator.ui.MyFirstPageLink.prototype = {
1845 current : null,
1845 current : null,
1846 leftmost_page: null,
1846 leftmost_page: null,
1847 rightmost_page: null,
1847 rightmost_page: null,
1848 link : null,
1848 link : null,
1849 span : null,
1849 span : null,
1850 dotdot : null,
1850 dotdot : null,
1851 getPos : function(cur_page, max_page, items){
1851 getPos : function(cur_page, max_page, items){
1852 var edge = parseInt(items / 2) + 1;
1852 var edge = parseInt(items / 2) + 1;
1853 if (cur_page <= edge){
1853 if (cur_page <= edge){
1854 var radius = Math.max(parseInt(items / 2), items - cur_page);
1854 var radius = Math.max(parseInt(items / 2), items - cur_page);
1855 }
1855 }
1856 else if ((max_page - cur_page) < edge) {
1856 else if ((max_page - cur_page) < edge) {
1857 var radius = (items - 1) - (max_page - cur_page);
1857 var radius = (items - 1) - (max_page - cur_page);
1858 }
1858 }
1859 else{
1859 else{
1860 var radius = parseInt(items / 2);
1860 var radius = parseInt(items / 2);
1861 }
1861 }
1862
1862
1863 var left = Math.max(1, (cur_page - (radius)))
1863 var left = Math.max(1, (cur_page - (radius)))
1864 var right = Math.min(max_page, cur_page + (radius))
1864 var right = Math.min(max_page, cur_page + (radius))
1865 return [left, cur_page, right]
1865 return [left, cur_page, right]
1866 },
1866 },
1867 render : function (id_base) {
1867 render : function (id_base) {
1868 var p = this.paginator,
1868 var p = this.paginator,
1869 c = p.get('firstPageLinkClass'),
1869 c = p.get('firstPageLinkClass'),
1870 label = p.get('firstPageLinkLabel'),
1870 label = p.get('firstPageLinkLabel'),
1871 title = p.get('firstPageLinkTitle');
1871 title = p.get('firstPageLinkTitle');
1872
1872
1873 this.link = document.createElement('a');
1873 this.link = document.createElement('a');
1874 this.span = document.createElement('span');
1874 this.span = document.createElement('span');
1875 $(this.span).hide();
1875 $(this.span).hide();
1876
1876
1877 var _pos = this.getPos(p.getCurrentPage(), p.getTotalPages(), 5);
1877 var _pos = this.getPos(p.getCurrentPage(), p.getTotalPages(), 5);
1878 this.leftmost_page = _pos[0];
1878 this.leftmost_page = _pos[0];
1879 this.rightmost_page = _pos[2];
1879 this.rightmost_page = _pos[2];
1880
1880
1881 setId(this.link, id_base + '-first-link');
1881 setId(this.link, id_base + '-first-link');
1882 this.link.href = '#';
1882 this.link.href = '#';
1883 this.link.className = c;
1883 this.link.className = c;
1884 this.link.innerHTML = label;
1884 this.link.innerHTML = label;
1885 this.link.title = title;
1885 this.link.title = title;
1886 YUE.on(this.link,'click',this.onClick,this,true);
1886 YUE.on(this.link,'click',this.onClick,this,true);
1887
1887
1888 setId(this.span, id_base + '-first-span');
1888 setId(this.span, id_base + '-first-span');
1889 this.span.className = c;
1889 this.span.className = c;
1890 this.span.innerHTML = label;
1890 this.span.innerHTML = label;
1891
1891
1892 this.current = p.getCurrentPage() > 1 ? this.link : this.span;
1892 this.current = p.getCurrentPage() > 1 ? this.link : this.span;
1893 return this.current;
1893 return this.current;
1894 },
1894 },
1895 update : function (e) {
1895 update : function (e) {
1896 var p = this.paginator;
1896 var p = this.paginator;
1897 var _pos = this.getPos(p.getCurrentPage(), p.getTotalPages(), 5);
1897 var _pos = this.getPos(p.getCurrentPage(), p.getTotalPages(), 5);
1898 this.leftmost_page = _pos[0];
1898 this.leftmost_page = _pos[0];
1899 this.rightmost_page = _pos[2];
1899 this.rightmost_page = _pos[2];
1900
1900
1901 if (e && e.prevValue === e.newValue) {
1901 if (e && e.prevValue === e.newValue) {
1902 return;
1902 return;
1903 }
1903 }
1904
1904
1905 var par = this.current ? this.current.parentNode : null;
1905 var par = this.current ? this.current.parentNode : null;
1906 if (this.leftmost_page > 1) {
1906 if (this.leftmost_page > 1) {
1907 if (par && this.current === this.span) {
1907 if (par && this.current === this.span) {
1908 par.replaceChild(this.link,this.current);
1908 par.replaceChild(this.link,this.current);
1909 this.current = this.link;
1909 this.current = this.link;
1910 }
1910 }
1911 } else {
1911 } else {
1912 if (par && this.current === this.link) {
1912 if (par && this.current === this.link) {
1913 par.replaceChild(this.span,this.current);
1913 par.replaceChild(this.span,this.current);
1914 this.current = this.span;
1914 this.current = this.span;
1915 }
1915 }
1916 }
1916 }
1917 },
1917 },
1918 destroy : function () {
1918 destroy : function () {
1919 YUE.purgeElement(this.link);
1919 YUE.purgeElement(this.link);
1920 this.current.parentNode.removeChild(this.current);
1920 this.current.parentNode.removeChild(this.current);
1921 this.link = this.span = null;
1921 this.link = this.span = null;
1922 },
1922 },
1923 onClick : function (e) {
1923 onClick : function (e) {
1924 YUE.stopEvent(e);
1924 YUE.stopEvent(e);
1925 this.paginator.setPage(1);
1925 this.paginator.setPage(1);
1926 }
1926 }
1927 };
1927 };
1928
1928
1929 })();
1929 })();
1930
1930
1931 (function () {
1931 (function () {
1932
1932
1933 var Paginator = YAHOO.widget.Paginator,
1933 var Paginator = YAHOO.widget.Paginator,
1934 l = YAHOO.lang,
1934 l = YAHOO.lang,
1935 setId = YAHOO.util.Dom.generateId;
1935 setId = YAHOO.util.Dom.generateId;
1936
1936
1937 Paginator.ui.MyLastPageLink = function (p) {
1937 Paginator.ui.MyLastPageLink = function (p) {
1938 this.paginator = p;
1938 this.paginator = p;
1939
1939
1940 p.subscribe('recordOffsetChange',this.update,this,true);
1940 p.subscribe('recordOffsetChange',this.update,this,true);
1941 p.subscribe('rowsPerPageChange',this.update,this,true);
1941 p.subscribe('rowsPerPageChange',this.update,this,true);
1942 p.subscribe('totalRecordsChange',this.update,this,true);
1942 p.subscribe('totalRecordsChange',this.update,this,true);
1943 p.subscribe('destroy',this.destroy,this,true);
1943 p.subscribe('destroy',this.destroy,this,true);
1944
1944
1945 // TODO: make this work
1945 // TODO: make this work
1946 p.subscribe('lastPageLinkLabelChange',this.update,this,true);
1946 p.subscribe('lastPageLinkLabelChange',this.update,this,true);
1947 p.subscribe('lastPageLinkClassChange', this.update,this,true);
1947 p.subscribe('lastPageLinkClassChange', this.update,this,true);
1948 };
1948 };
1949
1949
1950 Paginator.ui.MyLastPageLink.init = function (p) {
1950 Paginator.ui.MyLastPageLink.init = function (p) {
1951 p.setAttributeConfig('lastPageLinkLabel', {
1951 p.setAttributeConfig('lastPageLinkLabel', {
1952 value : -1,
1952 value : -1,
1953 validator : l.isString
1953 validator : l.isString
1954 });
1954 });
1955 p.setAttributeConfig('lastPageLinkClass', {
1955 p.setAttributeConfig('lastPageLinkClass', {
1956 value : 'yui-pg-last',
1956 value : 'yui-pg-last',
1957 validator : l.isString
1957 validator : l.isString
1958 });
1958 });
1959 p.setAttributeConfig('lastPageLinkTitle', {
1959 p.setAttributeConfig('lastPageLinkTitle', {
1960 value : 'Last Page',
1960 value : 'Last Page',
1961 validator : l.isString
1961 validator : l.isString
1962 });
1962 });
1963
1963
1964 };
1964 };
1965
1965
1966 Paginator.ui.MyLastPageLink.prototype = {
1966 Paginator.ui.MyLastPageLink.prototype = {
1967
1967
1968 current : null,
1968 current : null,
1969 leftmost_page: null,
1969 leftmost_page: null,
1970 rightmost_page: null,
1970 rightmost_page: null,
1971 link : null,
1971 link : null,
1972 span : null,
1972 span : null,
1973 dotdot : null,
1973 dotdot : null,
1974 na : null,
1974 na : null,
1975 getPos : function(cur_page, max_page, items){
1975 getPos : function(cur_page, max_page, items){
1976 var edge = parseInt(items / 2) + 1;
1976 var edge = parseInt(items / 2) + 1;
1977 if (cur_page <= edge){
1977 if (cur_page <= edge){
1978 var radius = Math.max(parseInt(items / 2), items - cur_page);
1978 var radius = Math.max(parseInt(items / 2), items - cur_page);
1979 }
1979 }
1980 else if ((max_page - cur_page) < edge) {
1980 else if ((max_page - cur_page) < edge) {
1981 var radius = (items - 1) - (max_page - cur_page);
1981 var radius = (items - 1) - (max_page - cur_page);
1982 }
1982 }
1983 else{
1983 else{
1984 var radius = parseInt(items / 2);
1984 var radius = parseInt(items / 2);
1985 }
1985 }
1986
1986
1987 var left = Math.max(1, (cur_page - (radius)))
1987 var left = Math.max(1, (cur_page - (radius)))
1988 var right = Math.min(max_page, cur_page + (radius))
1988 var right = Math.min(max_page, cur_page + (radius))
1989 return [left, cur_page, right]
1989 return [left, cur_page, right]
1990 },
1990 },
1991 render : function (id_base) {
1991 render : function (id_base) {
1992 var p = this.paginator,
1992 var p = this.paginator,
1993 c = p.get('lastPageLinkClass'),
1993 c = p.get('lastPageLinkClass'),
1994 label = p.get('lastPageLinkLabel'),
1994 label = p.get('lastPageLinkLabel'),
1995 last = p.getTotalPages(),
1995 last = p.getTotalPages(),
1996 title = p.get('lastPageLinkTitle');
1996 title = p.get('lastPageLinkTitle');
1997
1997
1998 var _pos = this.getPos(p.getCurrentPage(), p.getTotalPages(), 5);
1998 var _pos = this.getPos(p.getCurrentPage(), p.getTotalPages(), 5);
1999 this.leftmost_page = _pos[0];
1999 this.leftmost_page = _pos[0];
2000 this.rightmost_page = _pos[2];
2000 this.rightmost_page = _pos[2];
2001
2001
2002 this.link = document.createElement('a');
2002 this.link = document.createElement('a');
2003 this.span = document.createElement('span');
2003 this.span = document.createElement('span');
2004 $(this.span).hide();
2004 $(this.span).hide();
2005
2005
2006 this.na = this.span.cloneNode(false);
2006 this.na = this.span.cloneNode(false);
2007
2007
2008 setId(this.link, id_base + '-last-link');
2008 setId(this.link, id_base + '-last-link');
2009 this.link.href = '#';
2009 this.link.href = '#';
2010 this.link.className = c;
2010 this.link.className = c;
2011 this.link.innerHTML = label;
2011 this.link.innerHTML = label;
2012 this.link.title = title;
2012 this.link.title = title;
2013 YUE.on(this.link,'click',this.onClick,this,true);
2013 YUE.on(this.link,'click',this.onClick,this,true);
2014
2014
2015 setId(this.span, id_base + '-last-span');
2015 setId(this.span, id_base + '-last-span');
2016 this.span.className = c;
2016 this.span.className = c;
2017 this.span.innerHTML = label;
2017 this.span.innerHTML = label;
2018
2018
2019 setId(this.na, id_base + '-last-na');
2019 setId(this.na, id_base + '-last-na');
2020
2020
2021 if (this.rightmost_page < p.getTotalPages()){
2021 if (this.rightmost_page < p.getTotalPages()){
2022 this.current = this.link;
2022 this.current = this.link;
2023 }
2023 }
2024 else{
2024 else{
2025 this.current = this.span;
2025 this.current = this.span;
2026 }
2026 }
2027
2027
2028 this.current.innerHTML = p.getTotalPages();
2028 this.current.innerHTML = p.getTotalPages();
2029 return this.current;
2029 return this.current;
2030 },
2030 },
2031
2031
2032 update : function (e) {
2032 update : function (e) {
2033 var p = this.paginator;
2033 var p = this.paginator;
2034
2034
2035 var _pos = this.getPos(p.getCurrentPage(), p.getTotalPages(), 5);
2035 var _pos = this.getPos(p.getCurrentPage(), p.getTotalPages(), 5);
2036 this.leftmost_page = _pos[0];
2036 this.leftmost_page = _pos[0];
2037 this.rightmost_page = _pos[2];
2037 this.rightmost_page = _pos[2];
2038
2038
2039 if (e && e.prevValue === e.newValue) {
2039 if (e && e.prevValue === e.newValue) {
2040 return;
2040 return;
2041 }
2041 }
2042
2042
2043 var par = this.current ? this.current.parentNode : null,
2043 var par = this.current ? this.current.parentNode : null,
2044 after = this.link;
2044 after = this.link;
2045 if (par) {
2045 if (par) {
2046
2046
2047 // only show the last page if the rightmost one is
2047 // only show the last page if the rightmost one is
2048 // lower, so we don't have doubled entries at the end
2048 // lower, so we don't have doubled entries at the end
2049 if (!(this.rightmost_page < p.getTotalPages())){
2049 if (!(this.rightmost_page < p.getTotalPages())){
2050 after = this.span
2050 after = this.span
2051 }
2051 }
2052
2052
2053 if (this.current !== after) {
2053 if (this.current !== after) {
2054 par.replaceChild(after,this.current);
2054 par.replaceChild(after,this.current);
2055 this.current = after;
2055 this.current = after;
2056 }
2056 }
2057 }
2057 }
2058 this.current.innerHTML = this.paginator.getTotalPages();
2058 this.current.innerHTML = this.paginator.getTotalPages();
2059
2059
2060 },
2060 },
2061 destroy : function () {
2061 destroy : function () {
2062 YUE.purgeElement(this.link);
2062 YUE.purgeElement(this.link);
2063 this.current.parentNode.removeChild(this.current);
2063 this.current.parentNode.removeChild(this.current);
2064 this.link = this.span = null;
2064 this.link = this.span = null;
2065 },
2065 },
2066 onClick : function (e) {
2066 onClick : function (e) {
2067 YUE.stopEvent(e);
2067 YUE.stopEvent(e);
2068 this.paginator.setPage(this.paginator.getTotalPages());
2068 this.paginator.setPage(this.paginator.getTotalPages());
2069 }
2069 }
2070 };
2070 };
2071
2071
2072 })();
2072 })();
2073
2073
2074 var pagi = new YAHOO.widget.Paginator({
2074 var pagi = new YAHOO.widget.Paginator({
2075 rowsPerPage: links_per_page,
2075 rowsPerPage: links_per_page,
2076 alwaysVisible: false,
2076 alwaysVisible: false,
2077 template : "{PreviousPageLink} {MyFirstPageLink} {PageLinks} {MyLastPageLink} {NextPageLink}",
2077 template : "{PreviousPageLink} {MyFirstPageLink} {PageLinks} {MyLastPageLink} {NextPageLink}",
2078 pageLinks: 5,
2078 pageLinks: 5,
2079 containerClass: 'pagination-wh',
2079 containerClass: 'pagination-wh',
2080 currentPageClass: 'pager_curpage',
2080 currentPageClass: 'pager_curpage',
2081 pageLinkClass: 'pager_link',
2081 pageLinkClass: 'pager_link',
2082 nextPageLinkLabel: '&gt;',
2082 nextPageLinkLabel: '&gt;',
2083 previousPageLinkLabel: '&lt;',
2083 previousPageLinkLabel: '&lt;',
2084 containers:containers
2084 containers:containers
2085 })
2085 })
2086
2086
2087 return pagi
2087 return pagi
2088 }
2088 }
2089
2089
2090 var YUI_datatable = function(data, fields, columns, countnode, sortkey, rows){
2090 var YUI_datatable = function(data, fields, columns, countnode, sortkey, rows){
2091 var myDataSource = new YAHOO.util.DataSource(data);
2091 var myDataSource = new YAHOO.util.DataSource(data);
2092 myDataSource.responseType = YAHOO.util.DataSource.TYPE_JSON;
2092 myDataSource.responseType = YAHOO.util.DataSource.TYPE_JSON;
2093 myDataSource.responseSchema = {
2093 myDataSource.responseSchema = {
2094 resultsList: "records",
2094 resultsList: "records",
2095 fields: fields,
2095 fields: fields
2096 };
2096 };
2097 myDataSource.doBeforeCallback = function(req, raw, res, cb) {
2097 myDataSource.doBeforeCallback = function(req, raw, res, cb) {
2098 // This is the filter function
2098 // This is the filter function
2099 var data = res.results || [],
2099 var data = res.results || [],
2100 filtered = [],
2100 filtered = [],
2101 i, l;
2101 i, l;
2102
2102
2103 if (req) {
2103 if (req) {
2104 req = req.toLowerCase();
2104 req = req.toLowerCase();
2105 for (i = 0; i<data.length; i++) {
2105 for (i = 0; i<data.length; i++) {
2106 var pos = data[i].raw_name.toLowerCase().indexOf(req)
2106 var pos = data[i].raw_name.toLowerCase().indexOf(req)
2107 if (pos != -1) {
2107 if (pos != -1) {
2108 filtered.push(data[i]);
2108 filtered.push(data[i]);
2109 }
2109 }
2110 }
2110 }
2111 res.results = filtered;
2111 res.results = filtered;
2112 }
2112 }
2113 $(countnode).html(res.results.length);
2113 $(countnode).html(res.results.length);
2114 return res;
2114 return res;
2115 }
2115 }
2116
2116
2117 var myDataTable = new YAHOO.widget.DataTable("datatable_list_wrap", columns, myDataSource, {
2117 var myDataTable = new YAHOO.widget.DataTable("datatable_list_wrap", columns, myDataSource, {
2118 sortedBy: {key:sortkey, dir:"asc"},
2118 sortedBy: {key:sortkey, dir:"asc"},
2119 paginator: YUI_paginator(rows !== undefined && rows ? rows : 25, ['user-paginator']),
2119 paginator: YUI_paginator(rows !== undefined && rows ? rows : 25, ['user-paginator']),
2120 MSG_SORTASC: _TM['MSG_SORTASC'],
2120 MSG_SORTASC: _TM['MSG_SORTASC'],
2121 MSG_SORTDESC: _TM['MSG_SORTDESC'],
2121 MSG_SORTDESC: _TM['MSG_SORTDESC'],
2122 MSG_EMPTY: _TM['MSG_EMPTY'],
2122 MSG_EMPTY: _TM['MSG_EMPTY'],
2123 MSG_ERROR: _TM['MSG_ERROR'],
2123 MSG_ERROR: _TM['MSG_ERROR'],
2124 MSG_LOADING: _TM['MSG_LOADING'],
2124 MSG_LOADING: _TM['MSG_LOADING']
2125 });
2125 });
2126 myDataTable.subscribe('postRenderEvent',function(oArgs) {
2126 myDataTable.subscribe('postRenderEvent',function(oArgs) {
2127 tooltip_activate();
2127 tooltip_activate();
2128 quick_repo_menu();
2128 quick_repo_menu();
2129 });
2129 });
2130
2130
2131 var filterTimeout = null;
2131 var filterTimeout = null;
2132 var $q_filter = $('#q_filter');
2132 var $q_filter = $('#q_filter');
2133
2133
2134 updateFilter = function () {
2134 updateFilter = function () {
2135 // Reset timeout
2135 // Reset timeout
2136 filterTimeout = null;
2136 filterTimeout = null;
2137
2137
2138 // Reset sort
2138 // Reset sort
2139 var state = myDataTable.getState();
2139 var state = myDataTable.getState();
2140 state.sortedBy = {key:sortkey, dir:YAHOO.widget.DataTable.CLASS_ASC};
2140 state.sortedBy = {key:sortkey, dir:YAHOO.widget.DataTable.CLASS_ASC};
2141
2141
2142 // Get filtered data
2142 // Get filtered data
2143 myDataSource.sendRequest($q_filter.val(), {
2143 myDataSource.sendRequest($q_filter.val(), {
2144 success : myDataTable.onDataReturnInitializeTable,
2144 success : myDataTable.onDataReturnInitializeTable,
2145 failure : myDataTable.onDataReturnInitializeTable,
2145 failure : myDataTable.onDataReturnInitializeTable,
2146 scope : myDataTable,
2146 scope : myDataTable,
2147 argument: state});
2147 argument: state});
2148 };
2148 };
2149
2149
2150 $q_filter.click(function(){
2150 $q_filter.click(function(){
2151 if(!$q_filter.hasClass('loaded')){
2151 if(!$q_filter.hasClass('loaded')){
2152 //TODO: load here full list later to do search within groups
2152 //TODO: load here full list later to do search within groups
2153 $q_filter.addClass('loaded');
2153 $q_filter.addClass('loaded');
2154 }
2154 }
2155 });
2155 });
2156
2156
2157 $q_filter.keyup(function (e) {
2157 $q_filter.keyup(function (e) {
2158 clearTimeout(filterTimeout);
2158 clearTimeout(filterTimeout);
2159 filterTimeout = setTimeout(updateFilter, 600);
2159 filterTimeout = setTimeout(updateFilter, 600);
2160 });
2160 });
2161 }
2161 }
2162
2162
2163 // global hooks after DOM is loaded
2163 // global hooks after DOM is loaded
2164
2164
2165 $(document).ready(function(){
2165 $(document).ready(function(){
2166 $('.diff-collapse-button').click(function(e) {
2166 $('.diff-collapse-button').click(function(e) {
2167 var $button = $(e.currentTarget);
2167 var $button = $(e.currentTarget);
2168 var $target = $('#' + $button.attr('target'));
2168 var $target = $('#' + $button.attr('target'));
2169 if($target.hasClass('hidden')){
2169 if($target.hasClass('hidden')){
2170 $target.removeClass('hidden');
2170 $target.removeClass('hidden');
2171 $button.html("&uarr; {0} &uarr;".format(_TM['Collapse diff']));
2171 $button.html("&uarr; {0} &uarr;".format(_TM['Collapse diff']));
2172 }
2172 }
2173 else if(!$target.hasClass('hidden')){
2173 else if(!$target.hasClass('hidden')){
2174 $target.addClass('hidden');
2174 $target.addClass('hidden');
2175 $button.html("&darr; {0} &darr;".format(_TM['Expand diff']));
2175 $button.html("&darr; {0} &darr;".format(_TM['Expand diff']));
2176 }
2176 }
2177 });
2177 });
2178 });
2178 });
@@ -1,83 +1,83 b''
1 <div class="apikeys_wrap">
1 <div class="apikeys_wrap">
2 <table class="noborder">
2 <table class="noborder">
3 <tr>
3 <tr>
4 <td style="width: 450px"><div class="truncate autoexpand" style="width:120px;font-size:16px;font-family: monospace">${c.user.api_key}</div></td>
4 <td style="width: 450px"><div class="truncate autoexpand" style="width:120px;font-size:16px;font-family: monospace">${c.user.api_key}</div></td>
5 <td>
5 <td>
6 <span class="btn btn-mini btn-success disabled">${_('Built-in')}</span>
6 <span class="btn btn-mini btn-success disabled">${_('Built-in')}</span>
7 </td>
7 </td>
8 <td>${_('expires')}: ${_('never')}</td>
8 <td>${_('expires')}: ${_('never')}</td>
9 <td>
9 <td>
10 ${h.form(url('my_account_api_keys'),method='delete')}
10 ${h.form(url('my_account_api_keys'),method='delete')}
11 ${h.hidden('del_api_key',c.user.api_key)}
11 ${h.hidden('del_api_key',c.user.api_key)}
12 ${h.hidden('del_api_key_builtin',1)}
12 ${h.hidden('del_api_key_builtin',1)}
13 <button class="btn btn-mini btn-danger" type="submit"
13 <button class="btn btn-mini btn-danger" type="submit"
14 onclick="return confirm('${_('Confirm to reset this api key: %s') % c.user.api_key}');">
14 onclick="return confirm('${_('Confirm to reset this api key: %s') % c.user.api_key}');">
15 ${_('reset')}
15 ${_('reset')}
16 </button>
16 </button>
17 ${h.end_form()}
17 ${h.end_form()}
18 </td>
18 </td>
19 </tr>
19 </tr>
20 %if c.user_api_keys:
20 %if c.user_api_keys:
21 %for api_key in c.user_api_keys:
21 %for api_key in c.user_api_keys:
22 <tr class="${'expired' if api_key.expired else ''}">
22 <tr class="${'expired' if api_key.expired else ''}">
23 <td style="width: 450px"><div class="truncate autoexpand" style="width:120px;font-size:16px;font-family: monospace">${api_key.api_key}</div></td>
23 <td style="width: 450px"><div class="truncate autoexpand" style="width:120px;font-size:16px;font-family: monospace">${api_key.api_key}</div></td>
24 <td>${api_key.description}</td>
24 <td>${api_key.description}</td>
25 <td style="min-width: 80px">
25 <td style="min-width: 80px">
26 %if api_key.expires == -1:
26 %if api_key.expires == -1:
27 ${_('expires')}: ${_('never')}
27 ${_('expires')}: ${_('never')}
28 %else:
28 %else:
29 %if api_key.expired:
29 %if api_key.expired:
30 ${_('expired')}: ${h.age(h.time_to_datetime(api_key.expires))}
30 ${_('expired')}: ${h.age(h.time_to_datetime(api_key.expires))}
31 %else:
31 %else:
32 ${_('expires')}: ${h.age(h.time_to_datetime(api_key.expires))}
32 ${_('expires')}: ${h.age(h.time_to_datetime(api_key.expires))}
33 %endif
33 %endif
34 %endif
34 %endif
35 </td>
35 </td>
36 <td>
36 <td>
37 ${h.form(url('my_account_api_keys'),method='delete')}
37 ${h.form(url('my_account_api_keys'),method='delete')}
38 ${h.hidden('del_api_key',api_key.api_key)}
38 ${h.hidden('del_api_key',api_key.api_key)}
39 <button class="btn btn-mini btn-danger" type="submit"
39 <button class="btn btn-mini btn-danger" type="submit"
40 onclick="return confirm('${_('Confirm to remove this api key: %s') % api_key.api_key}');">
40 onclick="return confirm('${_('Confirm to remove this api key: %s') % api_key.api_key}');">
41 <i class="icon-remove-sign"></i>
41 <i class="icon-remove-sign"></i>
42 ${_('remove')}
42 ${_('remove')}
43 </button>
43 </button>
44 ${h.end_form()}
44 ${h.end_form()}
45 </td>
45 </td>
46 </tr>
46 </tr>
47 %endfor
47 %endfor
48 %else:
48 %else:
49 <tr><td><div class="ip">${_('No additional api keys specified')}</div></td></tr>
49 <tr><td><div class="ip">${_('No additional api keys specified')}</div></td></tr>
50 %endif
50 %endif
51 </table>
51 </table>
52 </div>
52 </div>
53
53
54 <div>
54 <div>
55 ${h.form(url('my_account_api_keys'), method='post')}
55 ${h.form(url('my_account_api_keys'), method='post')}
56 <div class="form">
56 <div class="form">
57 <!-- fields -->
57 <!-- fields -->
58 <div class="fields">
58 <div class="fields">
59 <div class="field">
59 <div class="field">
60 <div class="label">
60 <div class="label">
61 <label for="new_email">${_('New api key')}:</label>
61 <label for="new_email">${_('New api key')}:</label>
62 </div>
62 </div>
63 <div class="input">
63 <div class="input">
64 ${h.text('description', class_='medium', placeholder=_('Description'))}
64 ${h.text('description', class_='medium', placeholder=_('Description'))}
65 ${h.select('lifetime', '', c.lifetime_options)}
65 ${h.select('lifetime', '', c.lifetime_options)}
66 </div>
66 </div>
67 </div>
67 </div>
68 <div class="buttons">
68 <div class="buttons">
69 ${h.submit('save',_('Add'),class_="btn")}
69 ${h.submit('save',_('Add'),class_="btn")}
70 ${h.reset('reset',_('Reset'),class_="btn")}
70 ${h.reset('reset',_('Reset'),class_="btn")}
71 </div>
71 </div>
72 </div>
72 </div>
73 </div>
73 </div>
74 ${h.end_form()}
74 ${h.end_form()}
75 </div>
75 </div>
76
76
77 <script>
77 <script>
78 $(document).ready(function(){
78 $(document).ready(function(){
79 $("#lifetime").select2({
79 $("#lifetime").select2({
80 'dropdownAutoWidth': true,
80 'dropdownAutoWidth': true
81 });
81 });
82 })
82 })
83 </script>
83 </script>
@@ -1,107 +1,107 b''
1 <div style="font-size: 20px; color: #666666; padding: 0px 0px 10px 0px">${_('Repositories you are owner of')}</div>
1 <div style="font-size: 20px; color: #666666; padding: 0px 0px 10px 0px">${_('Repositories you are owner of')}</div>
2 <input class="q_filter_box" id="q_filter" size="15" type="text" name="filter"
2 <input class="q_filter_box" id="q_filter" size="15" type="text" name="filter"
3 placeholder="${_('quick filter...')}" value=""/>
3 placeholder="${_('quick filter...')}" value=""/>
4
4
5 <div class="table-grid table yui-skin-sam" id="repos_list_wrap"></div>
5 <div class="table-grid table yui-skin-sam" id="repos_list_wrap"></div>
6 <div id="user-paginator" style="padding: 0px 0px 0px 20px"></div>
6 <div id="user-paginator" style="padding: 0px 0px 0px 20px"></div>
7
7
8 <script>
8 <script>
9 function table_renderer(data){
9 function table_renderer(data){
10 var myDataSource = new YAHOO.util.DataSource(data);
10 var myDataSource = new YAHOO.util.DataSource(data);
11 myDataSource.responseType = YAHOO.util.DataSource.TYPE_JSON;
11 myDataSource.responseType = YAHOO.util.DataSource.TYPE_JSON;
12
12
13 myDataSource.responseSchema = {
13 myDataSource.responseSchema = {
14 resultsList: "records",
14 resultsList: "records",
15 fields: [
15 fields: [
16 {key:"menu"},
16 {key:"menu"},
17 {key:"raw_name"},
17 {key:"raw_name"},
18 {key:"name"},
18 {key:"name"},
19 {key:"last_changeset"},
19 {key:"last_changeset"},
20 {key:"last_rev_raw"},
20 {key:"last_rev_raw"},
21 {key:"action"},
21 {key:"action"}
22 ]
22 ]
23 };
23 };
24 myDataSource.doBeforeCallback = function(req,raw,res,cb) {
24 myDataSource.doBeforeCallback = function(req,raw,res,cb) {
25 // This is the filter function
25 // This is the filter function
26 var data = res.results || [],
26 var data = res.results || [],
27 filtered = [],
27 filtered = [],
28 i,l;
28 i,l;
29
29
30 if (req) {
30 if (req) {
31 req = req.toLowerCase();
31 req = req.toLowerCase();
32 for (i = 0; i<data.length; i++) {
32 for (i = 0; i<data.length; i++) {
33 var pos = data[i].raw_name.toLowerCase().indexOf(req)
33 var pos = data[i].raw_name.toLowerCase().indexOf(req)
34 if (pos != -1) {
34 if (pos != -1) {
35 filtered.push(data[i]);
35 filtered.push(data[i]);
36 }
36 }
37 }
37 }
38 res.results = filtered;
38 res.results = filtered;
39 }
39 }
40 return res;
40 return res;
41 }
41 }
42
42
43 // main table sorting
43 // main table sorting
44 var myColumnDefs = [
44 var myColumnDefs = [
45 {key:"menu",label:"",sortable:false,className:"quick_repo_menu hidden"},
45 {key:"menu",label:"",sortable:false,className:"quick_repo_menu hidden"},
46 {key:"name",label:"${_('Name')}",sortable:true,
46 {key:"name",label:"${_('Name')}",sortable:true,
47 sortOptions: { sortFunction: nameSort }},
47 sortOptions: { sortFunction: nameSort }},
48 {key:"last_changeset",label:"${_('Tip')}",sortable:true,
48 {key:"last_changeset",label:"${_('Tip')}",sortable:true,
49 sortOptions: { sortFunction: revisionSort }},
49 sortOptions: { sortFunction: revisionSort }},
50 {key:"action",label:"${_('Action')}",sortable:false},
50 {key:"action",label:"${_('Action')}",sortable:false}
51 ];
51 ];
52
52
53 var myDataTable = new YAHOO.widget.DataTable("repos_list_wrap", myColumnDefs, myDataSource,{
53 var myDataTable = new YAHOO.widget.DataTable("repos_list_wrap", myColumnDefs, myDataSource,{
54 sortedBy:{key:"name",dir:"asc"},
54 sortedBy:{key:"name",dir:"asc"},
55 paginator: YUI_paginator(50, ['user-paginator']),
55 paginator: YUI_paginator(50, ['user-paginator']),
56
56
57 MSG_SORTASC:"${_('Click to sort ascending')}",
57 MSG_SORTASC:"${_('Click to sort ascending')}",
58 MSG_SORTDESC:"${_('Click to sort descending')}",
58 MSG_SORTDESC:"${_('Click to sort descending')}",
59 MSG_EMPTY:"${_('No records found.')}",
59 MSG_EMPTY:"${_('No records found.')}",
60 MSG_ERROR:"${_('Data error.')}",
60 MSG_ERROR:"${_('Data error.')}",
61 MSG_LOADING:"${_('Loading...')}",
61 MSG_LOADING:"${_('Loading...')}"
62 }
62 }
63 );
63 );
64 myDataTable.subscribe('postRenderEvent',function(oArgs) {
64 myDataTable.subscribe('postRenderEvent',function(oArgs) {
65 tooltip_activate();
65 tooltip_activate();
66 quick_repo_menu();
66 quick_repo_menu();
67 });
67 });
68
68
69 var filterTimeout = null;
69 var filterTimeout = null;
70
70
71 updateFilter = function() {
71 updateFilter = function() {
72 // Reset timeout
72 // Reset timeout
73 filterTimeout = null;
73 filterTimeout = null;
74
74
75 // Reset sort
75 // Reset sort
76 var state = myDataTable.getState();
76 var state = myDataTable.getState();
77 state.sortedBy = {key:'name', dir:YAHOO.widget.DataTable.CLASS_ASC};
77 state.sortedBy = {key:'name', dir:YAHOO.widget.DataTable.CLASS_ASC};
78
78
79 // Get filtered data
79 // Get filtered data
80 myDataSource.sendRequest(YUD.get('q_filter').value,{
80 myDataSource.sendRequest(YUD.get('q_filter').value,{
81 success : myDataTable.onDataReturnInitializeTable,
81 success : myDataTable.onDataReturnInitializeTable,
82 failure : myDataTable.onDataReturnInitializeTable,
82 failure : myDataTable.onDataReturnInitializeTable,
83 scope : myDataTable,
83 scope : myDataTable,
84 argument: state
84 argument: state
85 });
85 });
86
86
87 };
87 };
88 $('#q_filter').click(function(){
88 $('#q_filter').click(function(){
89 if(!$('#q_filter').hasClass('loaded')){
89 if(!$('#q_filter').hasClass('loaded')){
90 //TODO: load here full list later to do search within groups
90 //TODO: load here full list later to do search within groups
91 $('#q_filter').addClass('loaded');
91 $('#q_filter').addClass('loaded');
92 }
92 }
93 });
93 });
94
94
95 $('#q_filter').keyup(function(){
95 $('#q_filter').keyup(function(){
96 clearTimeout(filterTimeout);
96 clearTimeout(filterTimeout);
97 filterTimeout = setTimeout(updateFilter,600);
97 filterTimeout = setTimeout(updateFilter,600);
98 });
98 });
99
99
100 if($('#q_filter').val()) {
100 if($('#q_filter').val()) {
101 updateFilter();
101 updateFilter();
102 }
102 }
103
103
104 }
104 }
105
105
106 table_renderer(${c.data |n});
106 table_renderer(${c.data |n});
107 </script>
107 </script>
@@ -1,107 +1,107 b''
1 <div style="font-size: 20px; color: #666666; padding: 0px 0px 10px 0px">${_('Repositories you are watching')}</div>
1 <div style="font-size: 20px; color: #666666; padding: 0px 0px 10px 0px">${_('Repositories you are watching')}</div>
2 <input class="q_filter_box" id="q_filter" size="15" type="text" name="filter"
2 <input class="q_filter_box" id="q_filter" size="15" type="text" name="filter"
3 placeholder="${_('quick filter...')}" value=""/>
3 placeholder="${_('quick filter...')}" value=""/>
4
4
5 <div class="table-grid table yui-skin-sam" id="repos_list_wrap"></div>
5 <div class="table-grid table yui-skin-sam" id="repos_list_wrap"></div>
6 <div id="user-paginator" style="padding: 0px 0px 0px 20px"></div>
6 <div id="user-paginator" style="padding: 0px 0px 0px 20px"></div>
7
7
8 <script>
8 <script>
9 function table_renderer(data){
9 function table_renderer(data){
10 var myDataSource = new YAHOO.util.DataSource(data);
10 var myDataSource = new YAHOO.util.DataSource(data);
11 myDataSource.responseType = YAHOO.util.DataSource.TYPE_JSON;
11 myDataSource.responseType = YAHOO.util.DataSource.TYPE_JSON;
12
12
13 myDataSource.responseSchema = {
13 myDataSource.responseSchema = {
14 resultsList: "records",
14 resultsList: "records",
15 fields: [
15 fields: [
16 {key:"menu"},
16 {key:"menu"},
17 {key:"raw_name"},
17 {key:"raw_name"},
18 {key:"name"},
18 {key:"name"},
19 {key:"last_changeset"},
19 {key:"last_changeset"},
20 {key:"last_rev_raw"},
20 {key:"last_rev_raw"},
21 {key:"action"},
21 {key:"action"}
22 ]
22 ]
23 };
23 };
24 myDataSource.doBeforeCallback = function(req,raw,res,cb) {
24 myDataSource.doBeforeCallback = function(req,raw,res,cb) {
25 // This is the filter function
25 // This is the filter function
26 var data = res.results || [],
26 var data = res.results || [],
27 filtered = [],
27 filtered = [],
28 i,l;
28 i,l;
29
29
30 if (req) {
30 if (req) {
31 req = req.toLowerCase();
31 req = req.toLowerCase();
32 for (i = 0; i<data.length; i++) {
32 for (i = 0; i<data.length; i++) {
33 var pos = data[i].raw_name.toLowerCase().indexOf(req)
33 var pos = data[i].raw_name.toLowerCase().indexOf(req)
34 if (pos != -1) {
34 if (pos != -1) {
35 filtered.push(data[i]);
35 filtered.push(data[i]);
36 }
36 }
37 }
37 }
38 res.results = filtered;
38 res.results = filtered;
39 }
39 }
40 return res;
40 return res;
41 }
41 }
42
42
43 // main table sorting
43 // main table sorting
44 var myColumnDefs = [
44 var myColumnDefs = [
45 {key:"menu",label:"",sortable:false,className:"quick_repo_menu hidden"},
45 {key:"menu",label:"",sortable:false,className:"quick_repo_menu hidden"},
46 {key:"name",label:"${_('Name')}",sortable:true,
46 {key:"name",label:"${_('Name')}",sortable:true,
47 sortOptions: { sortFunction: nameSort }},
47 sortOptions: { sortFunction: nameSort }},
48 {key:"last_changeset",label:"${_('Tip')}",sortable:true,
48 {key:"last_changeset",label:"${_('Tip')}",sortable:true,
49 sortOptions: { sortFunction: revisionSort }},
49 sortOptions: { sortFunction: revisionSort }},
50 {key:"action",label:"${_('Action')}",sortable:false},
50 {key:"action",label:"${_('Action')}",sortable:false}
51 ];
51 ];
52
52
53 var myDataTable = new YAHOO.widget.DataTable("repos_list_wrap", myColumnDefs, myDataSource,{
53 var myDataTable = new YAHOO.widget.DataTable("repos_list_wrap", myColumnDefs, myDataSource,{
54 sortedBy:{key:"name",dir:"asc"},
54 sortedBy:{key:"name",dir:"asc"},
55 paginator: YUI_paginator(50, ['user-paginator']),
55 paginator: YUI_paginator(50, ['user-paginator']),
56
56
57 MSG_SORTASC:"${_('Click to sort ascending')}",
57 MSG_SORTASC:"${_('Click to sort ascending')}",
58 MSG_SORTDESC:"${_('Click to sort descending')}",
58 MSG_SORTDESC:"${_('Click to sort descending')}",
59 MSG_EMPTY:"${_('No records found.')}",
59 MSG_EMPTY:"${_('No records found.')}",
60 MSG_ERROR:"${_('Data error.')}",
60 MSG_ERROR:"${_('Data error.')}",
61 MSG_LOADING:"${_('Loading...')}",
61 MSG_LOADING:"${_('Loading...')}"
62 }
62 }
63 );
63 );
64 myDataTable.subscribe('postRenderEvent',function(oArgs) {
64 myDataTable.subscribe('postRenderEvent',function(oArgs) {
65 tooltip_activate();
65 tooltip_activate();
66 quick_repo_menu();
66 quick_repo_menu();
67 });
67 });
68
68
69 var filterTimeout = null;
69 var filterTimeout = null;
70
70
71 updateFilter = function() {
71 updateFilter = function() {
72 // Reset timeout
72 // Reset timeout
73 filterTimeout = null;
73 filterTimeout = null;
74
74
75 // Reset sort
75 // Reset sort
76 var state = myDataTable.getState();
76 var state = myDataTable.getState();
77 state.sortedBy = {key:'name', dir:YAHOO.widget.DataTable.CLASS_ASC};
77 state.sortedBy = {key:'name', dir:YAHOO.widget.DataTable.CLASS_ASC};
78
78
79 // Get filtered data
79 // Get filtered data
80 myDataSource.sendRequest(YUD.get('q_filter').value,{
80 myDataSource.sendRequest(YUD.get('q_filter').value,{
81 success : myDataTable.onDataReturnInitializeTable,
81 success : myDataTable.onDataReturnInitializeTable,
82 failure : myDataTable.onDataReturnInitializeTable,
82 failure : myDataTable.onDataReturnInitializeTable,
83 scope : myDataTable,
83 scope : myDataTable,
84 argument: state
84 argument: state
85 });
85 });
86
86
87 };
87 };
88 $('#q_filter').click(function(){
88 $('#q_filter').click(function(){
89 if(!$('#q_filter').hasClass('loaded')){
89 if(!$('#q_filter').hasClass('loaded')){
90 //TODO: load here full list later to do search within groups
90 //TODO: load here full list later to do search within groups
91 $('#q_filter').addClass('loaded');
91 $('#q_filter').addClass('loaded');
92 }
92 }
93 });
93 });
94
94
95 $('#q_filter').keyup(function(){
95 $('#q_filter').keyup(function(){
96 clearTimeout(filterTimeout);
96 clearTimeout(filterTimeout);
97 filterTimeout = setTimeout(updateFilter,600);
97 filterTimeout = setTimeout(updateFilter,600);
98 });
98 });
99
99
100 if($('#q_filter').val()) {
100 if($('#q_filter').val()) {
101 updateFilter();
101 updateFilter();
102 }
102 }
103
103
104 }
104 }
105
105
106 table_renderer(${c.data |n});
106 table_renderer(${c.data |n});
107 </script>
107 </script>
@@ -1,27 +1,27 b''
1 <div style="font-size: 24px; color: #666666; padding: 0px 0px 10px 0px">${_('Repository Group: %s') % c.repo_group.group_name}</div>
1 <div style="font-size: 24px; color: #666666; padding: 0px 0px 10px 0px">${_('Repository Group: %s') % c.repo_group.group_name}</div>
2
2
3 <dl class="dl-horizontal">
3 <dl class="dl-horizontal">
4 <%
4 <%
5 elems = [
5 elems = [
6 (_('Top level repositories'), c.repo_group.repositories.count(), ''),
6 (_('Top level repositories'), c.repo_group.repositories.count(), ''),
7 (_('Total repositories'), c.repo_group.repositories_recursive_count, ''),
7 (_('Total repositories'), c.repo_group.repositories_recursive_count, ''),
8 (_('Children groups'), c.repo_group.children.count(), ''),
8 (_('Children groups'), c.repo_group.children.count(), ''),
9 (_('Created on'), h.fmt_date(c.repo_group.created_on), ''),
9 (_('Created on'), h.fmt_date(c.repo_group.created_on), ''),
10 (_('Owner'), h.person(c.repo_group.user.username), ''),
10 (_('Owner'), h.person(c.repo_group.user.username), '')
11 ]
11 ]
12 %>
12 %>
13 %for dt, dd, tt in elems:
13 %for dt, dd, tt in elems:
14 <dt style="width:150px; text-align: left">${dt}:</dt>
14 <dt style="width:150px; text-align: left">${dt}:</dt>
15 <dd style="margin-left: 160px" title="${tt}">${dd}</dd>
15 <dd style="margin-left: 160px" title="${tt}">${dd}</dd>
16 %endfor
16 %endfor
17 </dl>
17 </dl>
18
18
19 ${h.form(h.url('repos_group', group_name=c.repo_group.group_name),method='delete')}
19 ${h.form(h.url('repos_group', group_name=c.repo_group.group_name),method='delete')}
20 <button class="btn btn-small btn-danger" type="submit"
20 <button class="btn btn-small btn-danger" type="submit"
21 onclick="return confirm('${ungettext('Confirm to delete this group: %s with %s repository',
21 onclick="return confirm('${ungettext('Confirm to delete this group: %s with %s repository',
22 'Confirm to delete this group: %s with %s repositories',
22 'Confirm to delete this group: %s with %s repositories',
23 c.repo_group.repositories_recursive_count) % (c.repo_group.group_name, c.repo_group.repositories_recursive_count)}');">
23 c.repo_group.repositories_recursive_count) % (c.repo_group.group_name, c.repo_group.repositories_recursive_count)}');">
24 <i class="icon-remove-sign"></i>
24 <i class="icon-remove-sign"></i>
25 ${_('Delete this repository group')}
25 ${_('Delete this repository group')}
26 </button>
26 </button>
27 ${h.end_form()}
27 ${h.end_form()}
@@ -1,60 +1,59 b''
1 ## -*- coding: utf-8 -*-
1 ## -*- coding: utf-8 -*-
2 <%inherit file="/base/base.html"/>
2 <%inherit file="/base/base.html"/>
3
3
4 <%def name="title()">
4 <%def name="title()">
5 ${_('Repository groups administration')}
5 ${_('Repository groups administration')}
6 %if c.site_name:
6 %if c.site_name:
7 &middot; ${c.site_name}
7 &middot; ${c.site_name}
8 %endif
8 %endif
9 </%def>
9 </%def>
10
10
11 <%def name="breadcrumbs_links()">
11 <%def name="breadcrumbs_links()">
12 <input class="q_filter_box" id="q_filter" size="15" type="text" name="filter" placeholder="${_('quick filter...')}" value=""/>
12 <input class="q_filter_box" id="q_filter" size="15" type="text" name="filter" placeholder="${_('quick filter...')}" value=""/>
13 ${h.link_to(_('Admin'),h.url('admin_home'))} &raquo; <span id="repo_group_count">0</span> ${_('repository groups')}
13 ${h.link_to(_('Admin'),h.url('admin_home'))} &raquo; <span id="repo_group_count">0</span> ${_('repository groups')}
14 </%def>
14 </%def>
15
15
16
16
17 <%def name="page_nav()">
17 <%def name="page_nav()">
18 ${self.menu('admin')}
18 ${self.menu('admin')}
19 </%def>
19 </%def>
20
20
21 <%def name="main()">
21 <%def name="main()">
22 <div class="box">
22 <div class="box">
23 <!-- box / title -->
23 <!-- box / title -->
24 <div class="title">
24 <div class="title">
25 ${self.breadcrumbs()}
25 ${self.breadcrumbs()}
26 <ul class="links">
26 <ul class="links">
27 %if h.HasPermissionAny('hg.admin')():
27 %if h.HasPermissionAny('hg.admin')():
28 <li>
28 <li>
29 <a href="${h.url('new_repos_group')}" class="btn btn-small btn-success"><i class="icon-plus"></i> ${_(u'Add Repository Group')}</a>
29 <a href="${h.url('new_repos_group')}" class="btn btn-small btn-success"><i class="icon-plus"></i> ${_(u'Add Repository Group')}</a>
30 </li>
30 </li>
31 %endif
31 %endif
32 </ul>
32 </ul>
33 </div>
33 </div>
34 <!-- end box / title -->
34 <!-- end box / title -->
35 <div class="table-grid table yui-skin-sam" id="datatable_list_wrap"></div>
35 <div class="table-grid table yui-skin-sam" id="datatable_list_wrap"></div>
36 <div id="user-paginator" style="padding: 0px 0px 0px 20px"></div>
36 <div id="user-paginator" style="padding: 0px 0px 0px 20px"></div>
37 </div>
37 </div>
38 <script>
38 <script>
39 var data = ${c.data|n};
39 var data = ${c.data|n};
40 var fields = [
40 var fields = [
41 {key: "group_name"},
41 {key: "group_name"},
42 {key: "raw_name"},
42 {key: "raw_name"},
43 {key: "desc"},
43 {key: "desc"},
44 {key: "repos"},
44 {key: "repos"},
45 {key: "owner"},
45 {key: "owner"},
46 {key: "action"},
46 {key: "action"}
47
48 ];
47 ];
49 var column_defs = [
48 var column_defs = [
50 {key:"group_name",label:"${_('Name')}",sortable:true, sortOptions: { sortFunction: nameSort }},
49 {key:"group_name",label:"${_('Name')}",sortable:true, sortOptions: { sortFunction: nameSort }},
51 {key:"desc",label:"${_('Description')}",sortable:true},
50 {key:"desc",label:"${_('Description')}",sortable:true},
52 {key:"repos",label:"${_('Number of toplevel repositories')}",sortable:true},
51 {key:"repos",label:"${_('Number of toplevel repositories')}",sortable:true},
53 {key:"owner",label:"${_('Owner')}",sortable:true},
52 {key:"owner",label:"${_('Owner')}",sortable:true},
54 {key:"action",label:"${_('Action')}",sortable:false},
53 {key:"action",label:"${_('Action')}",sortable:false}
55 ];
54 ];
56 var counter = YUD.get('repo_group_count');
55 var counter = YUD.get('repo_group_count');
57 var sort_key = "group_name";
56 var sort_key = "group_name";
58 YUI_datatable(data, fields, column_defs, counter, sort_key, ${c.visual.admin_grid_items});
57 YUI_datatable(data, fields, column_defs, counter, sort_key, ${c.visual.admin_grid_items});
59 </script>
58 </script>
60 </%def>
59 </%def>
@@ -1,128 +1,128 b''
1 ## -*- coding: utf-8 -*-
1 ## -*- coding: utf-8 -*-
2
2
3 ${h.form(url('repos'))}
3 ${h.form(url('repos'))}
4 <div class="form">
4 <div class="form">
5 <!-- fields -->
5 <!-- fields -->
6 <div class="fields">
6 <div class="fields">
7 <div class="field">
7 <div class="field">
8 <div class="label">
8 <div class="label">
9 <label for="repo_name">${_('Name')}:</label>
9 <label for="repo_name">${_('Name')}:</label>
10 </div>
10 </div>
11 <div class="input">
11 <div class="input">
12 ${h.text('repo_name',class_="small")}
12 ${h.text('repo_name',class_="small")}
13 <div style="margin: 6px 0px 0px 0px">
13 <div style="margin: 6px 0px 0px 0px">
14 <a id="remote_clone_toggle" href="#"><i class="icon-download-alt"></i> ${_('Import existing repository ?')}</a>
14 <a id="remote_clone_toggle" href="#"><i class="icon-download-alt"></i> ${_('Import existing repository ?')}</a>
15 </div>
15 </div>
16 %if not c.authuser.is_admin:
16 %if not c.authuser.is_admin:
17 ${h.hidden('user_created',True)}
17 ${h.hidden('user_created',True)}
18 %endif
18 %endif
19 </div>
19 </div>
20 </div>
20 </div>
21 <div id="remote_clone" class="field" style="display: none">
21 <div id="remote_clone" class="field" style="display: none">
22 <div class="label">
22 <div class="label">
23 <label for="clone_uri">${_('Clone from')}:</label>
23 <label for="clone_uri">${_('Clone from')}:</label>
24 </div>
24 </div>
25 <div class="input">
25 <div class="input">
26 ${h.text('clone_uri',class_="small")}
26 ${h.text('clone_uri',class_="small")}
27 <span class="help-block">${_('Optional http[s] url from which repository should be cloned.')}</span>
27 <span class="help-block">${_('Optional http[s] url from which repository should be cloned.')}</span>
28 </div>
28 </div>
29 </div>
29 </div>
30 <div class="field">
30 <div class="field">
31 <div class="label label-textarea">
31 <div class="label label-textarea">
32 <label for="repo_description">${_('Description')}:</label>
32 <label for="repo_description">${_('Description')}:</label>
33 </div>
33 </div>
34 <div class="textarea-repo editor">
34 <div class="textarea-repo editor">
35 ${h.textarea('repo_description')}
35 ${h.textarea('repo_description')}
36 <span class="help-block">${_('Keep it short and to the point. Use a README file for longer descriptions.')}</span>
36 <span class="help-block">${_('Keep it short and to the point. Use a README file for longer descriptions.')}</span>
37 </div>
37 </div>
38 </div>
38 </div>
39 <div class="field">
39 <div class="field">
40 <div class="label">
40 <div class="label">
41 <label for="repo_group">${_('Repository group')}:</label>
41 <label for="repo_group">${_('Repository group')}:</label>
42 </div>
42 </div>
43 <div class="input">
43 <div class="input">
44 ${h.select('repo_group',request.GET.get('parent_group'),c.repo_groups,class_="medium")}
44 ${h.select('repo_group',request.GET.get('parent_group'),c.repo_groups,class_="medium")}
45 <span class="help-block">${_('Optionaly select a group to put this repository into.')}</span>
45 <span class="help-block">${_('Optionaly select a group to put this repository into.')}</span>
46 </div>
46 </div>
47 </div>
47 </div>
48 <div id="copy_perms" class="field">
48 <div id="copy_perms" class="field">
49 <div class="label label-checkbox">
49 <div class="label label-checkbox">
50 <label for="repo_copy_permissions">${_('Copy parent group permissions')}:</label>
50 <label for="repo_copy_permissions">${_('Copy parent group permissions')}:</label>
51 </div>
51 </div>
52 <div class="checkboxes">
52 <div class="checkboxes">
53 ${h.checkbox('repo_copy_permissions',value="True")}
53 ${h.checkbox('repo_copy_permissions',value="True")}
54 <span class="help-block">${_('Copy permission set from parent repository group.')}</span>
54 <span class="help-block">${_('Copy permission set from parent repository group.')}</span>
55 </div>
55 </div>
56 </div>
56 </div>
57 <div class="field">
57 <div class="field">
58 <div class="label">
58 <div class="label">
59 <label for="repo_type">${_('Type')}:</label>
59 <label for="repo_type">${_('Type')}:</label>
60 </div>
60 </div>
61 <div class="input">
61 <div class="input">
62 ${h.select('repo_type','hg',c.backends,class_="small")}
62 ${h.select('repo_type','hg',c.backends,class_="small")}
63 <span class="help-block">${_('Type of repository to create.')}</span>
63 <span class="help-block">${_('Type of repository to create.')}</span>
64 </div>
64 </div>
65 </div>
65 </div>
66 <div class="field">
66 <div class="field">
67 <div class="label">
67 <div class="label">
68 <label for="repo_landing_rev">${_('Landing revision')}:</label>
68 <label for="repo_landing_rev">${_('Landing revision')}:</label>
69 </div>
69 </div>
70 <div class="input">
70 <div class="input">
71 ${h.select('repo_landing_rev','',c.landing_revs,class_="medium")}
71 ${h.select('repo_landing_rev','',c.landing_revs,class_="medium")}
72 <span class="help-block">${_('Default revision for files page, downloads, full text search index and readme generation')}</span>
72 <span class="help-block">${_('Default revision for files page, downloads, full text search index and readme generation')}</span>
73 </div>
73 </div>
74 </div>
74 </div>
75 <div class="field">
75 <div class="field">
76 <div class="label label-checkbox">
76 <div class="label label-checkbox">
77 <label for="repo_private">${_('Private repository')}:</label>
77 <label for="repo_private">${_('Private repository')}:</label>
78 </div>
78 </div>
79 <div class="checkboxes">
79 <div class="checkboxes">
80 ${h.checkbox('repo_private',value="True")}
80 ${h.checkbox('repo_private',value="True")}
81 <span class="help-block">${_('Private repositories are only visible to people explicitly added as collaborators.')}</span>
81 <span class="help-block">${_('Private repositories are only visible to people explicitly added as collaborators.')}</span>
82 </div>
82 </div>
83 </div>
83 </div>
84 <div class="buttons">
84 <div class="buttons">
85 ${h.submit('add',_('Add'),class_="btn")}
85 ${h.submit('add',_('Add'),class_="btn")}
86 </div>
86 </div>
87 </div>
87 </div>
88 </div>
88 </div>
89 <script>
89 <script>
90 $(document).ready(function(){
90 $(document).ready(function(){
91 var setCopyPermsOption = function(group_val){
91 var setCopyPermsOption = function(group_val){
92 if(group_val != "-1"){
92 if(group_val != "-1"){
93 $('#copy_perms').show()
93 $('#copy_perms').show()
94 }
94 }
95 else{
95 else{
96 $('#copy_perms').hide();
96 $('#copy_perms').hide();
97 }
97 }
98 }
98 }
99
99
100 $('#remote_clone_toggle').on('click', function(e){
100 $('#remote_clone_toggle').on('click', function(e){
101 $('#remote_clone').show();
101 $('#remote_clone').show();
102 e.preventDefault();
102 e.preventDefault();
103 })
103 })
104 if($('#remote_clone input').hasClass('error')){
104 if($('#remote_clone input').hasClass('error')){
105 $('#remote_clone').show();
105 $('#remote_clone').show();
106 }
106 }
107 if($('#remote_clone input').val()){
107 if($('#remote_clone input').val()){
108 $('#remote_clone').show();
108 $('#remote_clone').show();
109 }
109 }
110 $("#repo_group").select2({
110 $("#repo_group").select2({
111 'dropdownAutoWidth': true
111 'dropdownAutoWidth': true
112 });
112 });
113
113
114 setCopyPermsOption($('#repo_group').val())
114 setCopyPermsOption($('#repo_group').val())
115 $("#repo_group").on("change", function(e) {
115 $("#repo_group").on("change", function(e) {
116 setCopyPermsOption(e.val)
116 setCopyPermsOption(e.val)
117 })
117 })
118
118
119 $("#repo_type").select2({
119 $("#repo_type").select2({
120 'minimumResultsForSearch': -1,
120 'minimumResultsForSearch': -1
121 });
121 });
122 $("#repo_landing_rev").select2({
122 $("#repo_landing_rev").select2({
123 'minimumResultsForSearch': -1,
123 'minimumResultsForSearch': -1
124 });
124 });
125 $('#repo_name').focus();
125 $('#repo_name').focus();
126 })
126 })
127 </script>
127 </script>
128 ${h.end_form()}
128 ${h.end_form()}
@@ -1,97 +1,97 b''
1 <h3>${_('Fork of')}</h3>
1 <h3>${_('Fork of')}</h3>
2 ${h.form(url('edit_repo_advanced_fork', repo_name=c.repo_info.repo_name), method='put')}
2 ${h.form(url('edit_repo_advanced_fork', repo_name=c.repo_info.repo_name), method='put')}
3 <div class="form">
3 <div class="form">
4 <div class="fields">
4 <div class="fields">
5 ${h.select('id_fork_of','',c.repos_list,class_="medium")}
5 ${h.select('id_fork_of','',c.repos_list,class_="medium")}
6 ${h.submit('set_as_fork_%s' % c.repo_info.repo_name,_('Set'),class_="btn btn-small",)}
6 ${h.submit('set_as_fork_%s' % c.repo_info.repo_name,_('Set'),class_="btn btn-small")}
7 </div>
7 </div>
8 <div class="field" style="border:none;color:#888">
8 <div class="field" style="border:none;color:#888">
9 <ul>
9 <ul>
10 <li>${_('''Manually set this repository as a fork of another from the list''')}</li>
10 <li>${_('''Manually set this repository as a fork of another from the list''')}</li>
11 </ul>
11 </ul>
12 </div>
12 </div>
13 </div>
13 </div>
14 ${h.end_form()}
14 ${h.end_form()}
15
15
16 <script>
16 <script>
17 $(document).ready(function(){
17 $(document).ready(function(){
18 $("#id_fork_of").select2({
18 $("#id_fork_of").select2({
19 'dropdownAutoWidth': true,
19 'dropdownAutoWidth': true
20 });
20 });
21 })
21 })
22 </script>
22 </script>
23
23
24 <h3>${_('Public journal visibility')}</h3>
24 <h3>${_('Public journal visibility')}</h3>
25 ${h.form(url('edit_repo_advanced_journal', repo_name=c.repo_info.repo_name), method='put')}
25 ${h.form(url('edit_repo_advanced_journal', repo_name=c.repo_info.repo_name), method='put')}
26 <div class="form">
26 <div class="form">
27 ${h.hidden('auth_token',str(h.get_token()))}
27 ${h.hidden('auth_token',str(h.get_token()))}
28 <div class="field">
28 <div class="field">
29 %if c.in_public_journal:
29 %if c.in_public_journal:
30 <button class="btn btn-small" type="submit">
30 <button class="btn btn-small" type="submit">
31 <i class="icon-minus"></i>
31 <i class="icon-minus"></i>
32 ${_('Remove from public journal')}
32 ${_('Remove from public journal')}
33 </button>
33 </button>
34 %else:
34 %else:
35 <button class="btn btn-small" type="submit">
35 <button class="btn btn-small" type="submit">
36 <i class="icon-plus"></i>
36 <i class="icon-plus"></i>
37 ${_('Add to public journal')}
37 ${_('Add to public journal')}
38 </button>
38 </button>
39 %endif
39 %endif
40 </div>
40 </div>
41 <div class="field" style="border:none;color:#888">
41 <div class="field" style="border:none;color:#888">
42 <ul>
42 <ul>
43 <li>${_('All actions made on this repository will be accessible to everyone in public journal')}</li>
43 <li>${_('All actions made on this repository will be accessible to everyone in public journal')}</li>
44 </ul>
44 </ul>
45 </div>
45 </div>
46 </div>
46 </div>
47 ${h.end_form()}
47 ${h.end_form()}
48
48
49 <h3>${_('Change locking')}</h3>
49 <h3>${_('Change locking')}</h3>
50 ${h.form(url('edit_repo_advanced_locking', repo_name=c.repo_info.repo_name), method='put')}
50 ${h.form(url('edit_repo_advanced_locking', repo_name=c.repo_info.repo_name), method='put')}
51 <div class="form">
51 <div class="form">
52 <div class="fields">
52 <div class="fields">
53 %if c.repo_info.locked[0]:
53 %if c.repo_info.locked[0]:
54 ${h.hidden('set_unlock', '1')}
54 ${h.hidden('set_unlock', '1')}
55 <button class="btn btn-small" type="submit"
55 <button class="btn btn-small" type="submit"
56 onclick="return confirm('${_('Confirm to unlock repository')}');">
56 onclick="return confirm('${_('Confirm to unlock repository')}');">
57 <i class="icon-unlock"></i>
57 <i class="icon-unlock"></i>
58 ${_('Unlock repository')}
58 ${_('Unlock repository')}
59 </button>
59 </button>
60 ${'Locked by %s on %s' % (h.person_by_id(c.repo_info.locked[0]),h.fmt_date(h.time_to_datetime(c.repo_info.locked[1])))}
60 ${'Locked by %s on %s' % (h.person_by_id(c.repo_info.locked[0]),h.fmt_date(h.time_to_datetime(c.repo_info.locked[1])))}
61 %else:
61 %else:
62 ${h.hidden('set_lock', '1')}
62 ${h.hidden('set_lock', '1')}
63 <button class="btn btn-small" type="submit"
63 <button class="btn btn-small" type="submit"
64 onclick="return confirm('${_('Confirm to lock repository')}');">
64 onclick="return confirm('${_('Confirm to lock repository')}');">
65 <i class="icon-lock"></i>
65 <i class="icon-lock"></i>
66 ${_('Lock repository')}
66 ${_('Lock repository')}
67 </button>
67 </button>
68 ${_('Repository is not locked')}
68 ${_('Repository is not locked')}
69 %endif
69 %endif
70 </div>
70 </div>
71 <div class="field" style="border:none;color:#888">
71 <div class="field" style="border:none;color:#888">
72 <ul>
72 <ul>
73 <li>${_('Force locking on repository. Works only when anonymous access is disabled. Trigering a pull locks repository by user who pulled, only the same user can unlock by doing a push')}
73 <li>${_('Force locking on repository. Works only when anonymous access is disabled. Trigering a pull locks repository by user who pulled, only the same user can unlock by doing a push')}
74 </li>
74 </li>
75 </ul>
75 </ul>
76 </div>
76 </div>
77 </div>
77 </div>
78 ${h.end_form()}
78 ${h.end_form()}
79
79
80 <h3>${_('Delete')}</h3>
80 <h3>${_('Delete')}</h3>
81 ${h.form(url('repo', repo_name=c.repo_name),method='delete')}
81 ${h.form(url('repo', repo_name=c.repo_name),method='delete')}
82 <button class="btn btn-small btn-danger" type="submit"
82 <button class="btn btn-small btn-danger" type="submit"
83 onclick="return confirm('${_('Confirm to delete this repository: %s') % c.repo_name}');">
83 onclick="return confirm('${_('Confirm to delete this repository: %s') % c.repo_name}');">
84 <i class="icon-remove-sign"></i>
84 <i class="icon-remove-sign"></i>
85 ${_('Delete this repository')}
85 ${_('Delete this repository')}
86 </button>
86 </button>
87 %if c.repo_info.forks.count():
87 %if c.repo_info.forks.count():
88 ${ungettext('this repository has %s fork', 'this repository has %s forks', c.repo_info.forks.count()) % c.repo_info.forks.count()}
88 ${ungettext('this repository has %s fork', 'this repository has %s forks', c.repo_info.forks.count()) % c.repo_info.forks.count()}
89 <input type="radio" name="forks" value="detach_forks" checked="checked"/> <label for="forks">${_('Detach forks')}</label>
89 <input type="radio" name="forks" value="detach_forks" checked="checked"/> <label for="forks">${_('Detach forks')}</label>
90 <input type="radio" name="forks" value="delete_forks" /> <label for="forks">${_('Delete forks')}</label>
90 <input type="radio" name="forks" value="delete_forks" /> <label for="forks">${_('Delete forks')}</label>
91 %endif
91 %endif
92 <div class="field" style="border:none;color:#888">
92 <div class="field" style="border:none;color:#888">
93 <ul>
93 <ul>
94 <li>${_('This repository will be renamed in a special way in order to be unaccesible for Kallithea and VCS systems. If you need to fully delete it from file system please do it manually')}</li>
94 <li>${_('This repository will be renamed in a special way in order to be unaccesible for Kallithea and VCS systems. If you need to fully delete it from file system please do it manually')}</li>
95 </ul>
95 </ul>
96 </div>
96 </div>
97 ${h.end_form()}
97 ${h.end_form()}
@@ -1,21 +1,21 b''
1 ${h.form(url('repo_as_fork', repo_name=c.repo_info.repo_name),method='put')}
1 ${h.form(url('repo_as_fork', repo_name=c.repo_info.repo_name),method='put')}
2 <div class="form">
2 <div class="form">
3 <div class="fields">
3 <div class="fields">
4 ${h.select('id_fork_of','',c.repos_list,class_="medium")}
4 ${h.select('id_fork_of','',c.repos_list,class_="medium")}
5 ${h.submit('set_as_fork_%s' % c.repo_info.repo_name,_('Set'),class_="btn btn-small",)}
5 ${h.submit('set_as_fork_%s' % c.repo_info.repo_name,_('Set'),class_="btn btn-small")}
6 </div>
6 </div>
7 <div class="field" style="border:none;color:#888">
7 <div class="field" style="border:none;color:#888">
8 <ul>
8 <ul>
9 <li>${_('''Manually set this repository as a fork of another from the list''')}</li>
9 <li>${_('''Manually set this repository as a fork of another from the list''')}</li>
10 </ul>
10 </ul>
11 </div>
11 </div>
12 </div>
12 </div>
13 ${h.end_form()}
13 ${h.end_form()}
14
14
15 <script>
15 <script>
16 $(document).ready(function(){
16 $(document).ready(function(){
17 $("#id_fork_of").select2({
17 $("#id_fork_of").select2({
18 'dropdownAutoWidth': true,
18 'dropdownAutoWidth': true
19 });
19 });
20 })
20 })
21 </script>
21 </script>
@@ -1,62 +1,62 b''
1 ## -*- coding: utf-8 -*-
1 ## -*- coding: utf-8 -*-
2 <%inherit file="/base/base.html"/>
2 <%inherit file="/base/base.html"/>
3
3
4 <%def name="title()">
4 <%def name="title()">
5 ${_('Repositories administration')}
5 ${_('Repositories administration')}
6 %if c.site_name:
6 %if c.site_name:
7 &middot; ${c.site_name}
7 &middot; ${c.site_name}
8 %endif
8 %endif
9 </%def>
9 </%def>
10
10
11 <%def name="breadcrumbs_links()">
11 <%def name="breadcrumbs_links()">
12 <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')}
12 <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')}
13 </%def>
13 </%def>
14 <%def name="page_nav()">
14 <%def name="page_nav()">
15 ${self.menu('admin')}
15 ${self.menu('admin')}
16 </%def>
16 </%def>
17 <%def name="main()">
17 <%def name="main()">
18 <div class="box">
18 <div class="box">
19
19
20 <div class="title">
20 <div class="title">
21 ${self.breadcrumbs()}
21 ${self.breadcrumbs()}
22 <ul class="links">
22 <ul class="links">
23 %if h.HasPermissionAny('hg.admin','hg.create.repository')():
23 %if h.HasPermissionAny('hg.admin','hg.create.repository')():
24 <li>
24 <li>
25 <a href="${h.url('new_repo')}" class="btn btn-small btn-success"><i class="icon-plus"></i> ${_(u'Add Repository')}</a>
25 <a href="${h.url('new_repo')}" class="btn btn-small btn-success"><i class="icon-plus"></i> ${_(u'Add Repository')}</a>
26 </li>
26 </li>
27 %endif
27 %endif
28 </ul>
28 </ul>
29 </div>
29 </div>
30 <div class="table-grid table yui-skin-sam" id="datatable_list_wrap"></div>
30 <div class="table-grid table yui-skin-sam" id="datatable_list_wrap"></div>
31 <div id="user-paginator" style="padding: 0px 0px 0px 20px"></div>
31 <div id="user-paginator" style="padding: 0px 0px 0px 20px"></div>
32
32
33
33
34 </div>
34 </div>
35 <script>
35 <script>
36 var data = ${c.data|n};
36 var data = ${c.data|n};
37 var fields = [
37 var fields = [
38 {key:"menu"},
38 {key:"menu"},
39 {key:"raw_name"},
39 {key:"raw_name"},
40 {key:"name"},
40 {key:"name"},
41 {key:"desc"},
41 {key:"desc"},
42 {key:"last_changeset"},
42 {key:"last_changeset"},
43 {key:"last_rev_raw"},
43 {key:"last_rev_raw"},
44 {key:"owner"},
44 {key:"owner"},
45 {key:"state"},
45 {key:"state"},
46 {key:"action"},
46 {key:"action"}
47 ];
47 ];
48 var column_defs = [
48 var column_defs = [
49 {key:"menu",label:"",sortable:false,className:"quick_repo_menu hidden"},
49 {key:"menu",label:"",sortable:false,className:"quick_repo_menu hidden"},
50 {key:"name",label:"${_('Name')}",sortable:true, sortOptions: { sortFunction: nameSort }},
50 {key:"name",label:"${_('Name')}",sortable:true, sortOptions: { sortFunction: nameSort }},
51 {key:"desc",label:"${_('Description')}",sortable:true},
51 {key:"desc",label:"${_('Description')}",sortable:true},
52 {key:"last_changeset",label:"${_('Tip')}",sortable:true, sortOptions: { sortFunction: revisionSort }},
52 {key:"last_changeset",label:"${_('Tip')}",sortable:true, sortOptions: { sortFunction: revisionSort }},
53 {key:"owner",label:"${_('Owner')}",sortable:true},
53 {key:"owner",label:"${_('Owner')}",sortable:true},
54 {key:"state",label:"${_('State')}",sortable:true},
54 {key:"state",label:"${_('State')}",sortable:true},
55 {key:"action",label:"${_('Action')}",sortable:false},
55 {key:"action",label:"${_('Action')}",sortable:false}
56 ];
56 ];
57 var counter = YUD.get('repo_count');
57 var counter = YUD.get('repo_count');
58 var sort_key = "name";
58 var sort_key = "name";
59 YUI_datatable(data, fields, column_defs, counter, sort_key, ${c.visual.admin_grid_items});
59 YUI_datatable(data, fields, column_defs, counter, sort_key, ${c.visual.admin_grid_items});
60 </script>
60 </script>
61
61
62 </%def>
62 </%def>
@@ -1,43 +1,43 b''
1 <dl class="dl-horizontal">
1 <dl class="dl-horizontal">
2 <%
2 <%
3 elems = [
3 elems = [
4 (_('Email prefix'), c.ini.get('email_prefix'), ''),
4 (_('Email prefix'), c.ini.get('email_prefix'), ''),
5 (_('Kallithea email from'), c.ini.get('app_email_from'), ''),
5 (_('Kallithea email from'), c.ini.get('app_email_from'), ''),
6 (_('Error email from'), c.ini.get('error_email_from'), ''),
6 (_('Error email from'), c.ini.get('error_email_from'), ''),
7 (_('Error email recipients'), c.ini.get('email_to'), ''),
7 (_('Error email recipients'), c.ini.get('email_to'), ''),
8
8
9 (_('SMTP server'), c.ini.get('smtp_server'), ''),
9 (_('SMTP server'), c.ini.get('smtp_server'), ''),
10 (_('SMTP username'), c.ini.get('smtp_username'), ''),
10 (_('SMTP username'), c.ini.get('smtp_username'), ''),
11 (_('SMTP password'), '%s chars' % len(c.ini.get('smtp_password', '')), ''),
11 (_('SMTP password'), '%s chars' % len(c.ini.get('smtp_password', '')), ''),
12 (_('SMTP port'), c.ini.get('smtp_port'), ''),
12 (_('SMTP port'), c.ini.get('smtp_port'), ''),
13
13
14 (_('SMTP use TLS'), c.ini.get('smtp_use_tls'), ''),
14 (_('SMTP use TLS'), c.ini.get('smtp_use_tls'), ''),
15 (_('SMTP use SSL'), c.ini.get('smtp_use_ssl'), ''),
15 (_('SMTP use SSL'), c.ini.get('smtp_use_ssl'), ''),
16 (_('SMTP auth'), c.ini.get('smtp_auth'), ''),
16 (_('SMTP auth'), c.ini.get('smtp_auth'), '')
17 ]
17 ]
18 %>
18 %>
19 %for dt, dd, tt in elems:
19 %for dt, dd, tt in elems:
20 <dt style="width:150px; text-align: left">${dt}:</dt>
20 <dt style="width:150px; text-align: left">${dt}:</dt>
21 <dd style="margin-left: 160px" title="${tt}">${dd}</dd>
21 <dd style="margin-left: 160px" title="${tt}">${dd}</dd>
22 %endfor
22 %endfor
23 </dl>
23 </dl>
24
24
25 ${h.form(url('admin_settings_email'), method='post')}
25 ${h.form(url('admin_settings_email'), method='post')}
26 <div class="form">
26 <div class="form">
27
27
28 <div class="fields">
28 <div class="fields">
29 <div class="field">
29 <div class="field">
30 <div class="label">
30 <div class="label">
31 <label for="test_email">${_('Send test email to')}:</label>
31 <label for="test_email">${_('Send test email to')}:</label>
32 </div>
32 </div>
33 <div class="input">
33 <div class="input">
34 ${h.text('test_email',size=30)}
34 ${h.text('test_email',size=30)}
35 </div>
35 </div>
36 </div>
36 </div>
37
37
38 <div class="buttons">
38 <div class="buttons">
39 ${h.submit('send',_('Send'),class_="btn")}
39 ${h.submit('send',_('Send'),class_="btn")}
40 </div>
40 </div>
41 </div>
41 </div>
42 </div>
42 </div>
43 ${h.end_form()}
43 ${h.end_form()}
@@ -1,75 +1,75 b''
1 <h4>${_('Built in Mercurial hooks - read only')}</h4>
1 <h4>${_('Built in Mercurial hooks - read only')}</h4>
2 <div class="form">
2 <div class="form">
3 <div class="fields">
3 <div class="fields">
4 % for hook in c.hooks:
4 % for hook in c.hooks:
5 <div class="field">
5 <div class="field">
6 <div class="label label">
6 <div class="label label">
7 <label for="${hook.ui_key}">${hook.ui_key}</label>
7 <label for="${hook.ui_key}">${hook.ui_key}</label>
8 </div>
8 </div>
9 <div class="input" style="margin-left:280px">
9 <div class="input" style="margin-left:280px">
10 ${h.text(hook.ui_key,hook.ui_value,size=60,readonly="readonly")}
10 ${h.text(hook.ui_key,hook.ui_value,size=60,readonly="readonly")}
11 </div>
11 </div>
12 </div>
12 </div>
13 % endfor
13 % endfor
14 </div>
14 </div>
15 <span class="help-block">${_('Hooks can be used to trigger actions on certain events such as push / pull. They can trigger Python functions or external applications.')}</span>
15 <span class="help-block">${_('Hooks can be used to trigger actions on certain events such as push / pull. They can trigger Python functions or external applications.')}</span>
16 </div>
16 </div>
17
17
18 % if c.visual.allow_custom_hooks_settings:
18 % if c.visual.allow_custom_hooks_settings:
19 <h4>${_('Custom hooks')}</h4>
19 <h4>${_('Custom hooks')}</h4>
20 ${h.form(url('admin_settings_hooks'), method='post')}
20 ${h.form(url('admin_settings_hooks'), method='post')}
21 <div class="form">
21 <div class="form">
22 <div class="fields">
22 <div class="fields">
23
23
24 % for hook in c.custom_hooks:
24 % for hook in c.custom_hooks:
25 <div class="field" id="${'id%s' % hook.ui_id }">
25 <div class="field" id="${'id%s' % hook.ui_id }">
26 <div class="label label">
26 <div class="label label">
27 <label for="${hook.ui_key}">${hook.ui_key}</label>
27 <label for="${hook.ui_key}">${hook.ui_key}</label>
28 </div>
28 </div>
29 <div class="input" style="margin-left:280px">
29 <div class="input" style="margin-left:280px">
30 ${h.hidden('hook_ui_key',hook.ui_key)}
30 ${h.hidden('hook_ui_key',hook.ui_key)}
31 ${h.hidden('hook_ui_value',hook.ui_value)}
31 ${h.hidden('hook_ui_value',hook.ui_value)}
32 ${h.text('hook_ui_value_new',hook.ui_value,size=60)}
32 ${h.text('hook_ui_value_new',hook.ui_value,size=60)}
33 <span class="action_button"
33 <span class="action_button"
34 onclick="ajaxActionHook(${hook.ui_id},'${'id%s' % hook.ui_id }')">
34 onclick="ajaxActionHook(${hook.ui_id},'${'id%s' % hook.ui_id }')">
35 <i class="icon-remove-sign" style="color:#FF4444"></i>
35 <i class="icon-remove-sign" style="color:#FF4444"></i>
36 ${_('delete')}
36 ${_('delete')}
37 </span>
37 </span>
38 </div>
38 </div>
39 </div>
39 </div>
40 % endfor
40 % endfor
41
41
42 <div class="field">
42 <div class="field">
43 <div class="input" style="margin-left:-135px;position: absolute;">
43 <div class="input" style="margin-left:-135px;position: absolute;">
44 <div class="input">
44 <div class="input">
45 ${h.text('new_hook_ui_key',size=30)}
45 ${h.text('new_hook_ui_key',size=30)}
46 </div>
46 </div>
47 </div>
47 </div>
48 <div class="input" style="margin-left:280px">
48 <div class="input" style="margin-left:280px">
49 ${h.text('new_hook_ui_value',size=60)}
49 ${h.text('new_hook_ui_value',size=60)}
50 </div>
50 </div>
51 </div>
51 </div>
52 <div class="buttons" style="margin-left:280px">
52 <div class="buttons" style="margin-left:280px">
53 ${h.submit('save',_('Save'),class_="btn")}
53 ${h.submit('save',_('Save'),class_="btn")}
54 </div>
54 </div>
55 </div>
55 </div>
56 </div>
56 </div>
57 ${h.end_form()}
57 ${h.end_form()}
58 % endif
58 % endif
59
59
60 <script type="text/javascript">
60 <script type="text/javascript">
61 function ajaxActionHook(hook_id,field_id) {
61 function ajaxActionHook(hook_id,field_id) {
62 var sUrl = "${h.url('admin_settings_hooks')}";
62 var sUrl = "${h.url('admin_settings_hooks')}";
63 var callback = {
63 var callback = {
64 success: function (o) {
64 success: function (o) {
65 var elem = YUD.get(""+field_id);
65 var elem = YUD.get(""+field_id);
66 elem.parentNode.removeChild(elem);
66 elem.parentNode.removeChild(elem);
67 },
67 },
68 failure: function (o) {
68 failure: function (o) {
69 alert("${_('Failed to remove hook')}");
69 alert("${_('Failed to remove hook')}");
70 },
70 }
71 };
71 };
72 var postData = '_method=delete&hook_id=' + hook_id;
72 var postData = '_method=delete&hook_id=' + hook_id;
73 var request = YAHOO.util.Connect.asyncRequest('POST', sUrl, callback, postData);
73 var request = YAHOO.util.Connect.asyncRequest('POST', sUrl, callback, postData);
74 };
74 };
75 </script>
75 </script>
@@ -1,43 +1,43 b''
1 <dl class="dl-horizontal">
1 <dl class="dl-horizontal">
2 <%
2 <%
3 elems = [
3 elems = [
4 (_('Kallithea version'), h.literal('%s <b><span style="color:#036185; text-decoration: underline;cursor: pointer" id="check_for_update" >%s</span></b>' % (c.kallithea_version, _('check for updates'))), ''),
4 (_('Kallithea version'), h.literal('%s <b><span style="color:#036185; text-decoration: underline;cursor: pointer" id="check_for_update" >%s</span></b>' % (c.kallithea_version, _('check for updates'))), ''),
5 (_('Python version'), c.py_version, ''),
5 (_('Python version'), c.py_version, ''),
6 (_('Platform'), c.platform, ''),
6 (_('Platform'), c.platform, ''),
7 (_('GIT version'), c.git_version, ''),
7 (_('GIT version'), c.git_version, ''),
8 (_('GIT path'), c.ini.get('git_path'), ''),
8 (_('GIT path'), c.ini.get('git_path'), ''),
9 (_('Upgrade info endpoint'), h.literal('%s <br/><span style="color:#999999">%s.</span>' % (c.update_url, _('Note: please make sure this server can access this url'))), ''),
9 (_('Upgrade info endpoint'), h.literal('%s <br/><span style="color:#999999">%s.</span>' % (c.update_url, _('Note: please make sure this server can access this url'))), '')
10 ]
10 ]
11 %>
11 %>
12
12
13 <div id="update_notice" style="display: none">
13 <div id="update_notice" style="display: none">
14 <div style="padding: 5px 0px 5px 0px; color: #000000; font-weight: bold">${_('Checking for updates...')}</div>
14 <div style="padding: 5px 0px 5px 0px; color: #000000; font-weight: bold">${_('Checking for updates...')}</div>
15 </div>
15 </div>
16 %for dt, dd, tt in elems:
16 %for dt, dd, tt in elems:
17 <dt style="width:150px; text-align: left">${dt}:</dt>
17 <dt style="width:150px; text-align: left">${dt}:</dt>
18 <dd style="margin-left: 160px" title="${tt}">${dd}</dd>
18 <dd style="margin-left: 160px" title="${tt}">${dd}</dd>
19 %endfor
19 %endfor
20 </dl>
20 </dl>
21
21
22 <h4>${_('Python packages')}</h4>
22 <h4>${_('Python packages')}</h4>
23 <table class="table" style="margin:0px 0px 0px 0px">
23 <table class="table" style="margin:0px 0px 0px 0px">
24 <colgroup>
24 <colgroup>
25 <col style="width:180px">
25 <col style="width:180px">
26 </colgroup>
26 </colgroup>
27 <tbody>
27 <tbody>
28 %for key, value in c.modules:
28 %for key, value in c.modules:
29 <tr>
29 <tr>
30 <td style="padding-right:5px;">${key}</td>
30 <td style="padding-right:5px;">${key}</td>
31 <td>${value}</td>
31 <td>${value}</td>
32 </tr>
32 </tr>
33 %endfor
33 %endfor
34 </tbody>
34 </tbody>
35 </table>
35 </table>
36
36
37 <script>
37 <script>
38 $('#check_for_update').click(function(e){
38 $('#check_for_update').click(function(e){
39 var $update_notice = $('#update_notice');
39 var $update_notice = $('#update_notice');
40 $update_notice.show();
40 $update_notice.show();
41 asynchtml("${h.url('admin_settings_system_update')}", $update_notice);
41 asynchtml("${h.url('admin_settings_system_update')}", $update_notice);
42 });
42 });
43 </script>
43 </script>
@@ -1,23 +1,23 b''
1 <div style="font-size: 24px; color: #666666; padding: 0px 0px 10px 0px">${_('User Group: %s') % c.user_group.users_group_name}</div>
1 <div style="font-size: 24px; color: #666666; padding: 0px 0px 10px 0px">${_('User Group: %s') % c.user_group.users_group_name}</div>
2
2
3 <dl class="dl-horizontal">
3 <dl class="dl-horizontal">
4 <%
4 <%
5 elems = [
5 elems = [
6 (_('Members'), len(c.group_members_obj), ''),
6 (_('Members'), len(c.group_members_obj), ''),
7 (_('Created on'), h.fmt_date(c.user_group.created_on), ''),
7 (_('Created on'), h.fmt_date(c.user_group.created_on), ''),
8 (_('Owner'), h.person(c.user_group.user.username), ''),
8 (_('Owner'), h.person(c.user_group.user.username), '')
9 ]
9 ]
10 %>
10 %>
11 %for dt, dd, tt in elems:
11 %for dt, dd, tt in elems:
12 <dt style="width:150px; text-align: left">${dt}:</dt>
12 <dt style="width:150px; text-align: left">${dt}:</dt>
13 <dd style="margin-left: 160px" title="${tt}">${dd}</dd>
13 <dd style="margin-left: 160px" title="${tt}">${dd}</dd>
14 %endfor
14 %endfor
15 </dl>
15 </dl>
16
16
17 ${h.form(h.url('users_group', id=c.user_group.users_group_id),method='delete')}
17 ${h.form(h.url('users_group', id=c.user_group.users_group_id),method='delete')}
18 <button class="btn btn-small btn-danger" type="submit"
18 <button class="btn btn-small btn-danger" type="submit"
19 onclick="return confirm('${_('Confirm to delete this user group: %s') % c.user_group.users_group_name}');">
19 onclick="return confirm('${_('Confirm to delete this user group: %s') % c.user_group.users_group_name}');">
20 <i class="icon-remove-sign"></i>
20 <i class="icon-remove-sign"></i>
21 ${_('Delete this user group')}
21 ${_('Delete this user group')}
22 </button>
22 </button>
23 ${h.end_form()}
23 ${h.end_form()}
@@ -1,61 +1,60 b''
1 ## -*- coding: utf-8 -*-
1 ## -*- coding: utf-8 -*-
2 <%inherit file="/base/base.html"/>
2 <%inherit file="/base/base.html"/>
3
3
4 <%def name="title()">
4 <%def name="title()">
5 ${_('User groups administration')}
5 ${_('User groups administration')}
6 %if c.site_name:
6 %if c.site_name:
7 &middot; ${c.site_name}
7 &middot; ${c.site_name}
8 %endif
8 %endif
9 </%def>
9 </%def>
10
10
11 <%def name="breadcrumbs_links()">
11 <%def name="breadcrumbs_links()">
12 <input class="q_filter_box" id="q_filter" size="15" type="text" name="filter" placeholder="${_('quick filter...')}" value=""/>
12 <input class="q_filter_box" id="q_filter" size="15" type="text" name="filter" placeholder="${_('quick filter...')}" value=""/>
13 ${h.link_to(_('Admin'),h.url('admin_home'))} &raquo; <span id="user_group_count">0</span> ${_('user groups')}
13 ${h.link_to(_('Admin'),h.url('admin_home'))} &raquo; <span id="user_group_count">0</span> ${_('user groups')}
14 </%def>
14 </%def>
15
15
16 <%def name="page_nav()">
16 <%def name="page_nav()">
17 ${self.menu('admin')}
17 ${self.menu('admin')}
18 </%def>
18 </%def>
19
19
20 <%def name="main()">
20 <%def name="main()">
21 <div class="box">
21 <div class="box">
22 <!-- box / title -->
22 <!-- box / title -->
23 <div class="title">
23 <div class="title">
24 ${self.breadcrumbs()}
24 ${self.breadcrumbs()}
25 <ul class="links">
25 <ul class="links">
26 %if h.HasPermissionAny('hg.admin', 'hg.usergroup.create.true')():
26 %if h.HasPermissionAny('hg.admin', 'hg.usergroup.create.true')():
27 <li>
27 <li>
28 <a href="${h.url('new_users_group')}" class="btn btn-small btn-success"><i class="icon-plus"></i> ${_(u'Add User Group')}</a>
28 <a href="${h.url('new_users_group')}" class="btn btn-small btn-success"><i class="icon-plus"></i> ${_(u'Add User Group')}</a>
29 </li>
29 </li>
30 %endif
30 %endif
31 </ul>
31 </ul>
32 </div>
32 </div>
33 <!-- end box / title -->
33 <!-- end box / title -->
34 <div class="table-grid table yui-skin-sam" id="datatable_list_wrap"></div>
34 <div class="table-grid table yui-skin-sam" id="datatable_list_wrap"></div>
35 <div id="user-paginator" style="padding: 0px 0px 0px 20px"></div>
35 <div id="user-paginator" style="padding: 0px 0px 0px 20px"></div>
36 </div>
36 </div>
37 <script>
37 <script>
38 var data = ${c.data|n};
38 var data = ${c.data|n};
39 var fields = [
39 var fields = [
40 {key: "group_name"},
40 {key: "group_name"},
41 {key: "raw_name"},
41 {key: "raw_name"},
42 {key: "desc"},
42 {key: "desc"},
43 {key: "members"},
43 {key: "members"},
44 {key: "active"},
44 {key: "active"},
45 {key: "owner"},
45 {key: "owner"},
46 {key: "action"},
46 {key: "action"}
47
48 ];
47 ];
49 var column_defs = [
48 var column_defs = [
50 {key:"group_name",label:"${_('Name')}",sortable:true, sortOptions: { sortFunction: nameSort }},
49 {key:"group_name",label:"${_('Name')}",sortable:true, sortOptions: { sortFunction: nameSort }},
51 {key:"desc",label:"${_('Description')}",sortable:true},
50 {key:"desc",label:"${_('Description')}",sortable:true},
52 {key:"members",label:"${_('Members')}",sortable:false},
51 {key:"members",label:"${_('Members')}",sortable:false},
53 {key:"active",label:"${_('Active')}",sortable:true,},
52 {key:"active",label:"${_('Active')}",sortable:true},
54 {key:"owner",label:"${_('Owner')}",sortable:true},
53 {key:"owner",label:"${_('Owner')}",sortable:true},
55 {key:"action",label:"${_('Action')}",sortable:false},
54 {key:"action",label:"${_('Action')}",sortable:false}
56 ];
55 ];
57 var counter = YUD.get('user_group_count');
56 var counter = YUD.get('user_group_count');
58 var sort_key = "group_name";
57 var sort_key = "group_name";
59 YUI_datatable(data, fields, column_defs, counter, sort_key, ${c.visual.admin_grid_items});
58 YUI_datatable(data, fields, column_defs, counter, sort_key, ${c.visual.admin_grid_items});
60 </script>
59 </script>
61 </%def>
60 </%def>
@@ -1,83 +1,83 b''
1 <div class="apikeys_wrap">
1 <div class="apikeys_wrap">
2 <table class="noborder">
2 <table class="noborder">
3 <tr>
3 <tr>
4 <td style="width: 450px"><div class="truncate autoexpand" style="width:120px;font-size:16px;font-family: monospace">${c.user.api_key}</div></td>
4 <td style="width: 450px"><div class="truncate autoexpand" style="width:120px;font-size:16px;font-family: monospace">${c.user.api_key}</div></td>
5 <td>
5 <td>
6 <span class="btn btn-mini btn-success disabled">${_('Built-in')}</span>
6 <span class="btn btn-mini btn-success disabled">${_('Built-in')}</span>
7 </td>
7 </td>
8 <td>${_('expires')}: ${_('never')}</td>
8 <td>${_('expires')}: ${_('never')}</td>
9 <td>
9 <td>
10 ${h.form(url('edit_user_api_keys', id=c.user.user_id),method='delete')}
10 ${h.form(url('edit_user_api_keys', id=c.user.user_id),method='delete')}
11 ${h.hidden('del_api_key',c.user.api_key)}
11 ${h.hidden('del_api_key',c.user.api_key)}
12 ${h.hidden('del_api_key_builtin',1)}
12 ${h.hidden('del_api_key_builtin',1)}
13 <button class="btn btn-mini btn-danger" type="submit"
13 <button class="btn btn-mini btn-danger" type="submit"
14 onclick="return confirm('${_('Confirm to reset this api key: %s') % c.user.api_key}');">
14 onclick="return confirm('${_('Confirm to reset this api key: %s') % c.user.api_key}');">
15 ${_('reset')}
15 ${_('reset')}
16 </button>
16 </button>
17 ${h.end_form()}
17 ${h.end_form()}
18 </td>
18 </td>
19 </tr>
19 </tr>
20 %if c.user_api_keys:
20 %if c.user_api_keys:
21 %for api_key in c.user_api_keys:
21 %for api_key in c.user_api_keys:
22 <tr class="${'expired' if api_key.expired else ''}">
22 <tr class="${'expired' if api_key.expired else ''}">
23 <td style="width: 450px"><div class="truncate autoexpand" style="width:120px;font-size:16px;font-family: monospace">${api_key.api_key}</div></td>
23 <td style="width: 450px"><div class="truncate autoexpand" style="width:120px;font-size:16px;font-family: monospace">${api_key.api_key}</div></td>
24 <td>${api_key.description}</td>
24 <td>${api_key.description}</td>
25 <td style="min-width: 80px">
25 <td style="min-width: 80px">
26 %if api_key.expires == -1:
26 %if api_key.expires == -1:
27 ${_('expires')}: ${_('never')}
27 ${_('expires')}: ${_('never')}
28 %else:
28 %else:
29 %if api_key.expired:
29 %if api_key.expired:
30 ${_('expired')}: ${h.age(h.time_to_datetime(api_key.expires))}
30 ${_('expired')}: ${h.age(h.time_to_datetime(api_key.expires))}
31 %else:
31 %else:
32 ${_('expires')}: ${h.age(h.time_to_datetime(api_key.expires))}
32 ${_('expires')}: ${h.age(h.time_to_datetime(api_key.expires))}
33 %endif
33 %endif
34 %endif
34 %endif
35 </td>
35 </td>
36 <td>
36 <td>
37 ${h.form(url('edit_user_api_keys', id=c.user.user_id),method='delete')}
37 ${h.form(url('edit_user_api_keys', id=c.user.user_id),method='delete')}
38 ${h.hidden('del_api_key',api_key.api_key)}
38 ${h.hidden('del_api_key',api_key.api_key)}
39 <button class="btn btn-mini btn-danger" type="submit"
39 <button class="btn btn-mini btn-danger" type="submit"
40 onclick="return confirm('${_('Confirm to remove this api key: %s') % api_key.api_key}');">
40 onclick="return confirm('${_('Confirm to remove this api key: %s') % api_key.api_key}');">
41 <i class="icon-remove-sign"></i>
41 <i class="icon-remove-sign"></i>
42 ${_('remove')}
42 ${_('remove')}
43 </button>
43 </button>
44 ${h.end_form()}
44 ${h.end_form()}
45 </td>
45 </td>
46 </tr>
46 </tr>
47 %endfor
47 %endfor
48 %else:
48 %else:
49 <tr><td><div class="ip">${_('No additional api keys specified')}</div></td></tr>
49 <tr><td><div class="ip">${_('No additional api keys specified')}</div></td></tr>
50 %endif
50 %endif
51 </table>
51 </table>
52 </div>
52 </div>
53
53
54 <div>
54 <div>
55 ${h.form(url('edit_user_api_keys', id=c.user.user_id), method='put')}
55 ${h.form(url('edit_user_api_keys', id=c.user.user_id), method='put')}
56 <div class="form">
56 <div class="form">
57 <!-- fields -->
57 <!-- fields -->
58 <div class="fields">
58 <div class="fields">
59 <div class="field">
59 <div class="field">
60 <div class="label">
60 <div class="label">
61 <label for="new_email">${_('New api key')}:</label>
61 <label for="new_email">${_('New api key')}:</label>
62 </div>
62 </div>
63 <div class="input">
63 <div class="input">
64 ${h.text('description', class_='medium', placeholder=_('Description'))}
64 ${h.text('description', class_='medium', placeholder=_('Description'))}
65 ${h.select('lifetime', '', c.lifetime_options)}
65 ${h.select('lifetime', '', c.lifetime_options)}
66 </div>
66 </div>
67 </div>
67 </div>
68 <div class="buttons">
68 <div class="buttons">
69 ${h.submit('save',_('Add'),class_="btn")}
69 ${h.submit('save',_('Add'),class_="btn")}
70 ${h.reset('reset',_('Reset'),class_="btn")}
70 ${h.reset('reset',_('Reset'),class_="btn")}
71 </div>
71 </div>
72 </div>
72 </div>
73 </div>
73 </div>
74 ${h.end_form()}
74 ${h.end_form()}
75 </div>
75 </div>
76
76
77 <script>
77 <script>
78 $(document).ready(function(){
78 $(document).ready(function(){
79 $("#lifetime").select2({
79 $("#lifetime").select2({
80 'dropdownAutoWidth': true,
80 'dropdownAutoWidth': true
81 });
81 });
82 })
82 })
83 </script>
83 </script>
@@ -1,67 +1,67 b''
1 ## -*- coding: utf-8 -*-
1 ## -*- coding: utf-8 -*-
2 <%inherit file="/base/base.html"/>
2 <%inherit file="/base/base.html"/>
3
3
4 <%def name="title()">
4 <%def name="title()">
5 ${_('Users administration')}
5 ${_('Users administration')}
6 %if c.site_name:
6 %if c.site_name:
7 &middot; ${c.site_name}
7 &middot; ${c.site_name}
8 %endif
8 %endif
9 </%def>
9 </%def>
10
10
11 <%def name="breadcrumbs_links()">
11 <%def name="breadcrumbs_links()">
12 <input class="q_filter_box" id="q_filter" size="15" type="text" name="filter" placeholder="${_('quick filter...')}" value=""/>
12 <input class="q_filter_box" id="q_filter" size="15" type="text" name="filter" placeholder="${_('quick filter...')}" value=""/>
13 ${h.link_to(_('Admin'),h.url('admin_home'))} &raquo; <span id="user_count">0</span> ${_('users')}
13 ${h.link_to(_('Admin'),h.url('admin_home'))} &raquo; <span id="user_count">0</span> ${_('users')}
14 </%def>
14 </%def>
15
15
16 <%def name="page_nav()">
16 <%def name="page_nav()">
17 ${self.menu('admin')}
17 ${self.menu('admin')}
18 </%def>
18 </%def>
19
19
20 <%def name="main()">
20 <%def name="main()">
21 <div class="box">
21 <div class="box">
22 <!-- box / title -->
22 <!-- box / title -->
23 <div class="title">
23 <div class="title">
24 ${self.breadcrumbs()}
24 ${self.breadcrumbs()}
25 <ul class="links">
25 <ul class="links">
26 <li>
26 <li>
27 <a href="${h.url('new_user')}" class="btn btn-small btn-success"><i class="icon-plus"></i> ${_(u'Add User')}</a>
27 <a href="${h.url('new_user')}" class="btn btn-small btn-success"><i class="icon-plus"></i> ${_(u'Add User')}</a>
28 </li>
28 </li>
29 </ul>
29 </ul>
30 </div>
30 </div>
31 <!-- end box / title -->
31 <!-- end box / title -->
32 <div class="table-grid table yui-skin-sam" id="datatable_list_wrap"></div>
32 <div class="table-grid table yui-skin-sam" id="datatable_list_wrap"></div>
33 <div id="user-paginator" style="padding: 0px 0px 0px 20px"></div>
33 <div id="user-paginator" style="padding: 0px 0px 0px 20px"></div>
34 </div>
34 </div>
35
35
36 <script>
36 <script>
37 var data = ${c.data|n};
37 var data = ${c.data|n};
38 var fields = [
38 var fields = [
39 {key: "gravatar"},
39 {key: "gravatar"},
40 {key: "raw_name"},
40 {key: "raw_name"},
41 {key: "username"},
41 {key: "username"},
42 {key: "firstname"},
42 {key: "firstname"},
43 {key: "lastname"},
43 {key: "lastname"},
44 {key: "last_login"},
44 {key: "last_login"},
45 {key: "last_login_raw"},
45 {key: "last_login_raw"},
46 {key: "active"},
46 {key: "active"},
47 {key: "admin"},
47 {key: "admin"},
48 {key: "extern_type"},
48 {key: "extern_type"},
49 {key: "action"},
49 {key: "action"}
50 ];
50 ];
51 var column_defs = [
51 var column_defs = [
52 {key:"gravatar",label:"",sortable:false,},
52 {key:"gravatar",label:"",sortable:false},
53 {key:"username",label:"${_('Username')}",sortable:true},
53 {key:"username",label:"${_('Username')}",sortable:true},
54 {key:"firstname",label:"${_('Firstname')}",sortable:true,},
54 {key:"firstname",label:"${_('Firstname')}",sortable:true},
55 {key:"lastname",label:"${_('Lastname')}",sortable:true,},
55 {key:"lastname",label:"${_('Lastname')}",sortable:true},
56 {key:"last_login",label:"${_('Last login')}",sortable:true, sortOptions: { sortFunction: lastLoginSort }},
56 {key:"last_login",label:"${_('Last login')}",sortable:true, sortOptions: { sortFunction: lastLoginSort }},
57 {key:"active",label:"${_('Active')}",sortable:true,},
57 {key:"active",label:"${_('Active')}",sortable:true},
58 {key:"admin",label:"${_('Admin')}",sortable:true,},
58 {key:"admin",label:"${_('Admin')}",sortable:true},
59 {key:"extern_type",label:"${_('Auth type')}",sortable:true,},
59 {key:"extern_type",label:"${_('Auth type')}",sortable:true},
60 {key:"action",label:"${_('Action')}",sortable:false},
60 {key:"action",label:"${_('Action')}",sortable:false}
61 ];
61 ];
62 var counter = YUD.get('user_count');
62 var counter = YUD.get('user_count');
63 var sort_key = "username";
63 var sort_key = "username";
64 YUI_datatable(data, fields, column_defs, counter, sort_key, ${c.visual.admin_grid_items});
64 YUI_datatable(data, fields, column_defs, counter, sort_key, ${c.visual.admin_grid_items});
65 </script>
65 </script>
66
66
67 </%def>
67 </%def>
@@ -1,605 +1,605 b''
1 ## -*- coding: utf-8 -*-
1 ## -*- coding: utf-8 -*-
2 <%inherit file="root.html"/>
2 <%inherit file="root.html"/>
3
3
4 <!-- HEADER -->
4 <!-- HEADER -->
5 <div id="header">
5 <div id="header">
6 <div id="header-inner" class="title">
6 <div id="header-inner" class="title">
7 <div id="logo">
7 <div id="logo">
8 <a href="${h.url('home')}" style="display: block;">
8 <a href="${h.url('home')}" style="display: block;">
9 <div class="header">
9 <div class="header">
10 <img src="${h.url('/images/kallithea-logo.svg')}" onerror="this.src='${h.url('/images/kallithea-logo.png')}'" alt="Kallithea"/>
10 <img src="${h.url('/images/kallithea-logo.svg')}" onerror="this.src='${h.url('/images/kallithea-logo.png')}'" alt="Kallithea"/>
11 </div>
11 </div>
12 %if c.site_name:
12 %if c.site_name:
13 <div class="branding">${c.site_name}</div>
13 <div class="branding">${c.site_name}</div>
14 %endif
14 %endif
15 </a>
15 </a>
16 </div>
16 </div>
17 <!-- MENU -->
17 <!-- MENU -->
18 ${self.page_nav()}
18 ${self.page_nav()}
19 <!-- END MENU -->
19 <!-- END MENU -->
20 ${self.body()}
20 ${self.body()}
21 </div>
21 </div>
22 </div>
22 </div>
23 <!-- END HEADER -->
23 <!-- END HEADER -->
24
24
25 <!-- CONTENT -->
25 <!-- CONTENT -->
26 <div id="content">
26 <div id="content">
27 ${self.flash_msg()}
27 ${self.flash_msg()}
28 <div id="main">
28 <div id="main">
29 ${next.main()}
29 ${next.main()}
30 </div>
30 </div>
31 </div>
31 </div>
32 <!-- END CONTENT -->
32 <!-- END CONTENT -->
33
33
34 <!-- FOOTER -->
34 <!-- FOOTER -->
35 <div id="footer">
35 <div id="footer">
36 <div id="footer-inner" class="title">
36 <div id="footer-inner" class="title">
37 <div>
37 <div>
38 <p class="footer-link">
38 <p class="footer-link">
39 ${_('Server instance: %s') % c.instance_id if c.instance_id else ''}
39 ${_('Server instance: %s') % c.instance_id if c.instance_id else ''}
40 </p>
40 </p>
41 <p class="footer-link-right">
41 <p class="footer-link-right">
42 This site is powered by
42 This site is powered by
43 %if c.visual.show_version:
43 %if c.visual.show_version:
44 <a href="${h.url('kallithea_project_url')}" target="_blank">Kallithea</a> ${c.kallithea_version},
44 <a href="${h.url('kallithea_project_url')}" target="_blank">Kallithea</a> ${c.kallithea_version},
45 %else:
45 %else:
46 <a href="${h.url('kallithea_project_url')}" target="_blank">Kallithea</a>,
46 <a href="${h.url('kallithea_project_url')}" target="_blank">Kallithea</a>,
47 %endif
47 %endif
48 which is
48 which is
49 <a href="${h.canonical_url('about')}#copyright">&copy; 2010&ndash;2014 by various authors &amp; licensed under GPLv3</a>.
49 <a href="${h.canonical_url('about')}#copyright">&copy; 2010&ndash;2014 by various authors &amp; licensed under GPLv3</a>.
50 %if c.issues_url:
50 %if c.issues_url:
51 &ndash; <a href="${c.issues_url}" target="_blank">${_('Support')}</a>
51 &ndash; <a href="${c.issues_url}" target="_blank">${_('Support')}</a>
52 %endif
52 %endif
53 </p>
53 </p>
54 </div>
54 </div>
55 </div>
55 </div>
56 </div>
56 </div>
57
57
58 <!-- END FOOTER -->
58 <!-- END FOOTER -->
59
59
60 ### MAKO DEFS ###
60 ### MAKO DEFS ###
61
61
62 <%def name="flash_msg()">
62 <%def name="flash_msg()">
63 <%include file="/base/flash_msg.html"/>
63 <%include file="/base/flash_msg.html"/>
64 </%def>
64 </%def>
65
65
66 <%def name="breadcrumbs()">
66 <%def name="breadcrumbs()">
67 <div class="breadcrumbs">
67 <div class="breadcrumbs">
68 ${self.breadcrumbs_links()}
68 ${self.breadcrumbs_links()}
69 </div>
69 </div>
70 </%def>
70 </%def>
71
71
72 <%def name="admin_menu()">
72 <%def name="admin_menu()">
73 <ul class="admin_menu">
73 <ul class="admin_menu">
74 <li><a href="${h.url('admin_home')}"><i class="icon-book"></i> ${_('Admin journal')}</a></li>
74 <li><a href="${h.url('admin_home')}"><i class="icon-book"></i> ${_('Admin journal')}</a></li>
75 <li><a href="${h.url('repos')}"><i class="icon-archive"></i> ${_('Repositories')}</a></li>
75 <li><a href="${h.url('repos')}"><i class="icon-archive"></i> ${_('Repositories')}</a></li>
76 <li><a href="${h.url('repos_groups')}"><i class="icon-folder-close"></i> ${_('Repository groups')}</a></li>
76 <li><a href="${h.url('repos_groups')}"><i class="icon-folder-close"></i> ${_('Repository groups')}</a></li>
77 <li><a href="${h.url('users')}"><i class="icon-user"></i> ${_('Users')}</a></li>
77 <li><a href="${h.url('users')}"><i class="icon-user"></i> ${_('Users')}</a></li>
78 <li><a href="${h.url('users_groups')}"><i class="icon-group"></i> ${_('User groups')}</a></li>
78 <li><a href="${h.url('users_groups')}"><i class="icon-group"></i> ${_('User groups')}</a></li>
79 <li><a href="${h.url('admin_permissions')}"><i class="icon-ban-circle"></i> ${_('Permissions')}</a></li>
79 <li><a href="${h.url('admin_permissions')}"><i class="icon-ban-circle"></i> ${_('Permissions')}</a></li>
80 <li><a href="${h.url('auth_home')}"><i class="icon-key"></i> ${_('Authentication')}</a></li>
80 <li><a href="${h.url('auth_home')}"><i class="icon-key"></i> ${_('Authentication')}</a></li>
81 <li><a href="${h.url('defaults')}"><i class="icon-wrench"></i> ${_('Defaults')}</a></li>
81 <li><a href="${h.url('defaults')}"><i class="icon-wrench"></i> ${_('Defaults')}</a></li>
82 <li class="last"><a href="${h.url('admin_settings')}"><i class="icon-cog"></i> ${_('Settings')}</a></li>
82 <li class="last"><a href="${h.url('admin_settings')}"><i class="icon-cog"></i> ${_('Settings')}</a></li>
83 </ul>
83 </ul>
84
84
85 </%def>
85 </%def>
86
86
87
87
88 ## admin menu used for people that have some admin resources
88 ## admin menu used for people that have some admin resources
89 <%def name="admin_menu_simple(repositories=None, repository_groups=None, user_groups=None)">
89 <%def name="admin_menu_simple(repositories=None, repository_groups=None, user_groups=None)">
90 <ul>
90 <ul>
91 %if repositories:
91 %if repositories:
92 <li><a href="${h.url('repos')}"><i class="icon-archive"></i> ${_('Repositories')}</a></li>
92 <li><a href="${h.url('repos')}"><i class="icon-archive"></i> ${_('Repositories')}</a></li>
93 %endif
93 %endif
94 %if repository_groups:
94 %if repository_groups:
95 <li><a href="${h.url('repos_groups')}"><i class="icon-folder-close"></i> ${_('Repository groups')}</a></li>
95 <li><a href="${h.url('repos_groups')}"><i class="icon-folder-close"></i> ${_('Repository groups')}</a></li>
96 %endif
96 %endif
97 %if user_groups:
97 %if user_groups:
98 <li><a href="${h.url('users_groups')}"><i class="icon-group"></i> ${_('User groups')}</a></li>
98 <li><a href="${h.url('users_groups')}"><i class="icon-group"></i> ${_('User groups')}</a></li>
99 %endif
99 %endif
100 </ul>
100 </ul>
101 </%def>
101 </%def>
102
102
103 <%def name="repo_context_bar(current=None, rev=None)">
103 <%def name="repo_context_bar(current=None, rev=None)">
104 <% rev = None if rev == 'tip' else rev %>
104 <% rev = None if rev == 'tip' else rev %>
105 <%
105 <%
106 def follow_class():
106 def follow_class():
107 if c.repository_following:
107 if c.repository_following:
108 return h.literal('following')
108 return h.literal('following')
109 else:
109 else:
110 return h.literal('follow')
110 return h.literal('follow')
111 %>
111 %>
112 <%
112 <%
113 def is_current(selected):
113 def is_current(selected):
114 if selected == current:
114 if selected == current:
115 return h.literal('class="current"')
115 return h.literal('class="current"')
116 %>
116 %>
117
117
118 <!--- CONTEXT BAR -->
118 <!--- CONTEXT BAR -->
119 <div id="context-bar" class="box">
119 <div id="context-bar" class="box">
120 <h2>
120 <h2>
121 %if h.is_hg(c.db_repo):
121 %if h.is_hg(c.db_repo):
122 <i class="icon-hg" style="color: #576622; font-size: 24px"></i>
122 <i class="icon-hg" style="color: #576622; font-size: 24px"></i>
123 %endif
123 %endif
124 %if h.is_git(c.db_repo):
124 %if h.is_git(c.db_repo):
125 <i class="icon-git" style="color: #e85634; font-size: 24px"></i>
125 <i class="icon-git" style="color: #e85634; font-size: 24px"></i>
126 %endif
126 %endif
127
127
128 ## public/private
128 ## public/private
129 %if c.db_repo.private:
129 %if c.db_repo.private:
130 <i class="icon-lock"></i>
130 <i class="icon-lock"></i>
131 %else:
131 %else:
132 <i class="icon-unlock-alt"></i>
132 <i class="icon-unlock-alt"></i>
133 %endif
133 %endif
134 ${h.repo_link(c.db_repo.groups_and_repo)}
134 ${h.repo_link(c.db_repo.groups_and_repo)}
135
135
136 %if current == 'createfork':
136 %if current == 'createfork':
137 - ${_('Create fork')}
137 - ${_('Create fork')}
138 %endif
138 %endif
139 </h2>
139 </h2>
140 <!--
140 <!--
141 <div id="breadcrumbs">
141 <div id="breadcrumbs">
142 ${h.link_to(_(u'Repositories'),h.url('home'))}
142 ${h.link_to(_(u'Repositories'),h.url('home'))}
143 &raquo;
143 &raquo;
144 ${h.repo_link(c.db_repo.groups_and_repo)}
144 ${h.repo_link(c.db_repo.groups_and_repo)}
145 </div>
145 </div>
146 -->
146 -->
147 <ul id="context-pages" class="horizontal-list">
147 <ul id="context-pages" class="horizontal-list">
148 <li ${is_current('summary')}><a href="${h.url('summary_home', repo_name=c.repo_name)}"><i class="icon-file-text"></i> ${_('Summary')}</a></li>
148 <li ${is_current('summary')}><a href="${h.url('summary_home', repo_name=c.repo_name)}"><i class="icon-file-text"></i> ${_('Summary')}</a></li>
149 %if rev:
149 %if rev:
150 <li ${is_current('changelog')}><a href="${h.url('changelog_file_home', repo_name=c.repo_name, revision=rev, f_path='')}"><i class="icon-time"></i> ${_('Changelog')}</a></li>
150 <li ${is_current('changelog')}><a href="${h.url('changelog_file_home', repo_name=c.repo_name, revision=rev, f_path='')}"><i class="icon-time"></i> ${_('Changelog')}</a></li>
151 %else:
151 %else:
152 <li ${is_current('changelog')}><a href="${h.url('changelog_home', repo_name=c.repo_name)}"><i class="icon-time"></i> ${_('Changelog')}</a></li>
152 <li ${is_current('changelog')}><a href="${h.url('changelog_home', repo_name=c.repo_name)}"><i class="icon-time"></i> ${_('Changelog')}</a></li>
153 %endif
153 %endif
154 <li ${is_current('files')}><a href="${h.url('files_home', repo_name=c.repo_name, revision=rev or 'tip')}"><i class="icon-file"></i> ${_('Files')}</a></li>
154 <li ${is_current('files')}><a href="${h.url('files_home', repo_name=c.repo_name, revision=rev or 'tip')}"><i class="icon-file"></i> ${_('Files')}</a></li>
155 <li ${is_current('switch-to')}>
155 <li ${is_current('switch-to')}>
156 <a href="#" id="branch_tag_switcher_2" class="dropdown"><i class="icon-random"></i> ${_('Switch To')}</a>
156 <a href="#" id="branch_tag_switcher_2" class="dropdown"><i class="icon-random"></i> ${_('Switch To')}</a>
157 <ul id="switch_to_list_2" class="switch_to submenu">
157 <ul id="switch_to_list_2" class="switch_to submenu">
158 <li><a href="#">${_('Loading...')}</a></li>
158 <li><a href="#">${_('Loading...')}</a></li>
159 </ul>
159 </ul>
160 </li>
160 </li>
161 <li ${is_current('options')}>
161 <li ${is_current('options')}>
162 %if h.HasRepoPermissionAll('repository.admin')(c.repo_name):
162 %if h.HasRepoPermissionAll('repository.admin')(c.repo_name):
163 <a href="${h.url('edit_repo',repo_name=c.repo_name)}" class="dropdown"><i class="icon-cogs"></i> ${_('Options')}</a>
163 <a href="${h.url('edit_repo',repo_name=c.repo_name)}" class="dropdown"><i class="icon-cogs"></i> ${_('Options')}</a>
164 %else:
164 %else:
165 <a href="#" class="dropdown"><i class="icon-cogs"></i> ${_('Options')}</a>
165 <a href="#" class="dropdown"><i class="icon-cogs"></i> ${_('Options')}</a>
166 %endif
166 %endif
167 <ul>
167 <ul>
168 %if h.HasRepoPermissionAll('repository.admin')(c.repo_name):
168 %if h.HasRepoPermissionAll('repository.admin')(c.repo_name):
169 <li><a href="${h.url('edit_repo',repo_name=c.repo_name)}"><i class="icon-cog"></i> ${_('Settings')}</a></li>
169 <li><a href="${h.url('edit_repo',repo_name=c.repo_name)}"><i class="icon-cog"></i> ${_('Settings')}</a></li>
170 %endif
170 %endif
171 %if c.db_repo.fork:
171 %if c.db_repo.fork:
172 <li><a href="${h.url('compare_url',repo_name=c.db_repo.fork.repo_name,org_ref_type=c.db_repo.landing_rev[0],org_ref_name=c.db_repo.landing_rev[1], other_repo=c.repo_name,other_ref_type='branch' if request.GET.get('branch') else c.db_repo.landing_rev[0],other_ref_name=request.GET.get('branch') or c.db_repo.landing_rev[1], merge=1)}">
172 <li><a href="${h.url('compare_url',repo_name=c.db_repo.fork.repo_name,org_ref_type=c.db_repo.landing_rev[0],org_ref_name=c.db_repo.landing_rev[1], other_repo=c.repo_name,other_ref_type='branch' if request.GET.get('branch') else c.db_repo.landing_rev[0],other_ref_name=request.GET.get('branch') or c.db_repo.landing_rev[1], merge=1)}">
173 <i class="icon-loop"></i> ${_('Compare fork')}</a></li>
173 <i class="icon-loop"></i> ${_('Compare fork')}</a></li>
174 %endif
174 %endif
175 <li><a href="${h.url('compare_home',repo_name=c.repo_name)}"><i class="icon-loop"></i> ${_('Compare')}</a></li>
175 <li><a href="${h.url('compare_home',repo_name=c.repo_name)}"><i class="icon-loop"></i> ${_('Compare')}</a></li>
176
176
177 <li><a href="${h.url('search_repo',repo_name=c.repo_name)}"><i class="icon-search"></i> ${_('Search')}</a></li>
177 <li><a href="${h.url('search_repo',repo_name=c.repo_name)}"><i class="icon-search"></i> ${_('Search')}</a></li>
178
178
179 %if h.HasRepoPermissionAny('repository.write','repository.admin')(c.repo_name) and c.db_repo.enable_locking:
179 %if h.HasRepoPermissionAny('repository.write','repository.admin')(c.repo_name) and c.db_repo.enable_locking:
180 %if c.db_repo.locked[0]:
180 %if c.db_repo.locked[0]:
181 <li>${h.link_to(_('Unlock'), h.url('toggle_locking',repo_name=c.repo_name),class_='locking_del')}</li>
181 <li>${h.link_to(_('Unlock'), h.url('toggle_locking',repo_name=c.repo_name),class_='locking_del')}</li>
182 %else:
182 %else:
183 <li>${h.link_to(_('Lock'), h.url('toggle_locking',repo_name=c.repo_name),class_='locking_add')}</li>
183 <li>${h.link_to(_('Lock'), h.url('toggle_locking',repo_name=c.repo_name),class_='locking_add')}</li>
184 %endif
184 %endif
185 %endif
185 %endif
186 ## TODO: this check feels wrong, it would be better to have a check for permissions
186 ## TODO: this check feels wrong, it would be better to have a check for permissions
187 ## also it feels like a job for the controller
187 ## also it feels like a job for the controller
188 %if c.authuser.username != 'default':
188 %if c.authuser.username != 'default':
189 <li>
189 <li>
190 <a class="${follow_class()}" onclick="javascript:toggleFollowingRepo(this,${c.db_repo.repo_id},'${str(h.get_token())}');">
190 <a class="${follow_class()}" onclick="javascript:toggleFollowingRepo(this,${c.db_repo.repo_id},'${str(h.get_token())}');">
191 <span class="show-follow"><i class="icon-heart-empty"></i> ${_('Follow')}</span>
191 <span class="show-follow"><i class="icon-heart-empty"></i> ${_('Follow')}</span>
192 <span class="show-following"><i class="icon-heart"></i> ${_('Unfollow')}</span>
192 <span class="show-following"><i class="icon-heart"></i> ${_('Unfollow')}</span>
193 </a>
193 </a>
194 </li>
194 </li>
195 <li><a href="${h.url('repo_fork_home',repo_name=c.repo_name)}"><i class="icon-code-fork"></i> ${_('Fork')}</a></li>
195 <li><a href="${h.url('repo_fork_home',repo_name=c.repo_name)}"><i class="icon-code-fork"></i> ${_('Fork')}</a></li>
196 <li><a href="${h.url('pullrequest_home',repo_name=c.repo_name)}"><i class="icon-code-fork"></i> ${_('Create Pull Request')}</a></li>
196 <li><a href="${h.url('pullrequest_home',repo_name=c.repo_name)}"><i class="icon-code-fork"></i> ${_('Create Pull Request')}</a></li>
197 %endif
197 %endif
198 </ul>
198 </ul>
199 </li>
199 </li>
200 <li ${is_current('showpullrequest')}>
200 <li ${is_current('showpullrequest')}>
201 <a href="${h.url('pullrequest_show_all',repo_name=c.repo_name)}" title="${_('Show Pull Requests for %s') % c.repo_name}"> <i class="icon-code-fork"></i> ${_('Pull Requests')}
201 <a href="${h.url('pullrequest_show_all',repo_name=c.repo_name)}" title="${_('Show Pull Requests for %s') % c.repo_name}"> <i class="icon-code-fork"></i> ${_('Pull Requests')}
202 %if c.repository_pull_requests:
202 %if c.repository_pull_requests:
203 <span>${c.repository_pull_requests}</span>
203 <span>${c.repository_pull_requests}</span>
204 %endif
204 %endif
205 </a>
205 </a>
206 </li>
206 </li>
207 </ul>
207 </ul>
208 </div>
208 </div>
209 <script type="text/javascript">
209 <script type="text/javascript">
210 YUE.on('branch_tag_switcher_2','mouseover',function(){
210 YUE.on('branch_tag_switcher_2','mouseover',function(){
211 var $branch_tag_switcher_2 = $('#branch_tag_switcher_2');
211 var $branch_tag_switcher_2 = $('#branch_tag_switcher_2');
212 var loaded = $branch_tag_switcher_2.hasClass('loaded');
212 var loaded = $branch_tag_switcher_2.hasClass('loaded');
213 if(!loaded){
213 if(!loaded){
214 $branch_tag_switcher_2.addClass('loaded');
214 $branch_tag_switcher_2.addClass('loaded');
215 asynchtml("${h.url('branch_tag_switcher',repo_name=c.repo_name)}", $('#switch_to_list_2'));
215 asynchtml("${h.url('branch_tag_switcher',repo_name=c.repo_name)}", $('#switch_to_list_2'));
216 }
216 }
217 return false;
217 return false;
218 });
218 });
219 </script>
219 </script>
220 <!--- END CONTEXT BAR -->
220 <!--- END CONTEXT BAR -->
221 </%def>
221 </%def>
222
222
223 <%def name="menu(current=None)">
223 <%def name="menu(current=None)">
224 <%
224 <%
225 def is_current(selected):
225 def is_current(selected):
226 if selected == current:
226 if selected == current:
227 return h.literal('class="current"')
227 return h.literal('class="current"')
228 %>
228 %>
229
229
230 <ul id="quick" class="horizontal-list">
230 <ul id="quick" class="horizontal-list">
231 <!-- repo switcher -->
231 <!-- repo switcher -->
232 <li ${is_current('repositories')}>
232 <li ${is_current('repositories')}>
233 <input id="repo_switcher" name="repo_switcher" type="hidden">
233 <input id="repo_switcher" name="repo_switcher" type="hidden">
234 </li>
234 </li>
235
235
236 ##ROOT MENU
236 ##ROOT MENU
237 %if c.authuser.username != 'default':
237 %if c.authuser.username != 'default':
238 <li ${is_current('journal')}>
238 <li ${is_current('journal')}>
239 <a class="menu_link" title="${_('Show recent activity')}" href="${h.url('journal')}">
239 <a class="menu_link" title="${_('Show recent activity')}" href="${h.url('journal')}">
240 <i class="icon-book"></i> ${_('Journal')}
240 <i class="icon-book"></i> ${_('Journal')}
241 </a>
241 </a>
242 </li>
242 </li>
243 %else:
243 %else:
244 <li ${is_current('journal')}>
244 <li ${is_current('journal')}>
245 <a class="menu_link" title="${_('Public journal')}" href="${h.url('public_journal')}">
245 <a class="menu_link" title="${_('Public journal')}" href="${h.url('public_journal')}">
246 <i class="icon-book"></i> ${_('Public journal')}
246 <i class="icon-book"></i> ${_('Public journal')}
247 </a>
247 </a>
248 </li>
248 </li>
249 %endif
249 %endif
250 <li ${is_current('gists')}>
250 <li ${is_current('gists')}>
251 <a class="menu_link childs" title="${_('Show public gists')}" href="${h.url('gists')}">
251 <a class="menu_link childs" title="${_('Show public gists')}" href="${h.url('gists')}">
252 <i class="icon-file-2"></i> ${_('Gists')}
252 <i class="icon-file-2"></i> ${_('Gists')}
253 </a>
253 </a>
254 <ul class="admin_menu">
254 <ul class="admin_menu">
255 <li><a href="${h.url('new_gist', public=1)}"><i class="icon-file-alt"></i> ${_('Create new gist')}</a></li>
255 <li><a href="${h.url('new_gist', public=1)}"><i class="icon-file-alt"></i> ${_('Create new gist')}</a></li>
256 <li><a href="${h.url('gists')}"><i class="icon-copy"></i> ${_('All public gists')}</a></li>
256 <li><a href="${h.url('gists')}"><i class="icon-copy"></i> ${_('All public gists')}</a></li>
257 %if c.authuser.username != 'default':
257 %if c.authuser.username != 'default':
258 <li><a href="${h.url('gists', public=1)}"><i class="icon-copy"></i> ${_('My public gists')}</a></li>
258 <li><a href="${h.url('gists', public=1)}"><i class="icon-copy"></i> ${_('My public gists')}</a></li>
259 <li><a href="${h.url('gists', private=1)}"><i class="icon-file-text"></i> ${_('My private gists')}</a></li>
259 <li><a href="${h.url('gists', private=1)}"><i class="icon-file-text"></i> ${_('My private gists')}</a></li>
260 %endif
260 %endif
261 </ul>
261 </ul>
262 </li>
262 </li>
263 <li ${is_current('search')}>
263 <li ${is_current('search')}>
264 <a class="menu_link" title="${_('Search in repositories')}" href="${h.url('search')}">
264 <a class="menu_link" title="${_('Search in repositories')}" href="${h.url('search')}">
265 <i class="icon-search"></i> ${_('Search')}
265 <i class="icon-search"></i> ${_('Search')}
266 </a>
266 </a>
267 </li>
267 </li>
268 % if h.HasPermissionAll('hg.admin')('access admin main page'):
268 % if h.HasPermissionAll('hg.admin')('access admin main page'):
269 <li ${is_current('admin')}>
269 <li ${is_current('admin')}>
270 <a class="menu_link childs" title="${_('Admin')}" href="${h.url('admin_home')}">
270 <a class="menu_link childs" title="${_('Admin')}" href="${h.url('admin_home')}">
271 <i class="icon-cog"></i> ${_('Admin')}
271 <i class="icon-cog"></i> ${_('Admin')}
272 </a>
272 </a>
273 ${admin_menu()}
273 ${admin_menu()}
274 </li>
274 </li>
275 % elif c.authuser.repositories_admin or c.authuser.repository_groups_admin or c.authuser.user_groups_admin:
275 % elif c.authuser.repositories_admin or c.authuser.repository_groups_admin or c.authuser.user_groups_admin:
276 <li ${is_current('admin')}>
276 <li ${is_current('admin')}>
277 <a class="menu_link childs" title="${_('Admin')}">
277 <a class="menu_link childs" title="${_('Admin')}">
278 <i class="icon-cog"></i> ${_('Admin')}
278 <i class="icon-cog"></i> ${_('Admin')}
279 </a>
279 </a>
280 ${admin_menu_simple(c.authuser.repositories_admin,
280 ${admin_menu_simple(c.authuser.repositories_admin,
281 c.authuser.repository_groups_admin,
281 c.authuser.repository_groups_admin,
282 c.authuser.user_groups_admin or h.HasPermissionAny('hg.usergroup.create.true')())}
282 c.authuser.user_groups_admin or h.HasPermissionAny('hg.usergroup.create.true')())}
283 </li>
283 </li>
284 % endif
284 % endif
285
285
286 <li ${is_current('my_pullrequests')}>
286 <li ${is_current('my_pullrequests')}>
287 <a class="menu_link" title="${_('My Pull Requests')}" href="${h.url('my_pullrequests')}">
287 <a class="menu_link" title="${_('My Pull Requests')}" href="${h.url('my_pullrequests')}">
288 <i class="icon-code-fork"></i> ${_('My Pull Requests')}
288 <i class="icon-code-fork"></i> ${_('My Pull Requests')}
289 %if c.my_pr_count != 0:
289 %if c.my_pr_count != 0:
290 <span class="menu_link_notifications">${c.my_pr_count}</span>
290 <span class="menu_link_notifications">${c.my_pr_count}</span>
291 %endif
291 %endif
292 </a>
292 </a>
293 </li>
293 </li>
294
294
295 ## USER MENU
295 ## USER MENU
296 <li>
296 <li>
297 <a class="menu_link childs" id="quick_login_link">
297 <a class="menu_link childs" id="quick_login_link">
298 <span class="icon">
298 <span class="icon">
299 <img src="${h.gravatar_url(c.authuser.email,20)}" alt="avatar">
299 <img src="${h.gravatar_url(c.authuser.email,20)}" alt="avatar">
300 </span>
300 </span>
301 %if c.authuser.username != 'default':
301 %if c.authuser.username != 'default':
302 <span class="menu_link_user">${c.authuser.username}</span>
302 <span class="menu_link_user">${c.authuser.username}</span>
303 %if c.unread_notifications != 0:
303 %if c.unread_notifications != 0:
304 <span class="menu_link_notifications">${c.unread_notifications}</span>
304 <span class="menu_link_notifications">${c.unread_notifications}</span>
305 %endif
305 %endif
306 %else:
306 %else:
307 <span>${_('Not logged in')}</span>
307 <span>${_('Not logged in')}</span>
308 %endif
308 %endif
309 </a>
309 </a>
310
310
311 <div class="user-menu">
311 <div class="user-menu">
312 <div id="quick_login">
312 <div id="quick_login">
313 %if c.authuser.username == 'default' or c.authuser.user_id is None:
313 %if c.authuser.username == 'default' or c.authuser.user_id is None:
314 <h4>${_('Login to your account')}</h4>
314 <h4>${_('Login to your account')}</h4>
315 ${h.form(h.url('login_home',came_from=h.url.current()))}
315 ${h.form(h.url('login_home',came_from=h.url.current()))}
316 <div class="form">
316 <div class="form">
317 <div class="fields">
317 <div class="fields">
318 <div class="field">
318 <div class="field">
319 <div class="label">
319 <div class="label">
320 <label for="username">${_('Username')}:</label>
320 <label for="username">${_('Username')}:</label>
321 </div>
321 </div>
322 <div class="input">
322 <div class="input">
323 ${h.text('username',class_='focus')}
323 ${h.text('username',class_='focus')}
324 </div>
324 </div>
325
325
326 </div>
326 </div>
327 <div class="field">
327 <div class="field">
328 <div class="label">
328 <div class="label">
329 <label for="password">${_('Password')}:</label>
329 <label for="password">${_('Password')}:</label>
330 </div>
330 </div>
331 <div class="input">
331 <div class="input">
332 ${h.password('password',class_='focus')}
332 ${h.password('password',class_='focus')}
333 </div>
333 </div>
334
334
335 </div>
335 </div>
336 <div class="buttons">
336 <div class="buttons">
337 <div class="password_forgoten">${h.link_to(_('Forgot password ?'),h.url('reset_password'))}</div>
337 <div class="password_forgoten">${h.link_to(_('Forgot password ?'),h.url('reset_password'))}</div>
338 <div class="register">
338 <div class="register">
339 %if h.HasPermissionAny('hg.admin', 'hg.register.auto_activate', 'hg.register.manual_activate')():
339 %if h.HasPermissionAny('hg.admin', 'hg.register.auto_activate', 'hg.register.manual_activate')():
340 ${h.link_to(_("Don't have an account ?"),h.url('register'))}
340 ${h.link_to(_("Don't have an account ?"),h.url('register'))}
341 %endif
341 %endif
342 </div>
342 </div>
343 <div class="submit">
343 <div class="submit">
344 ${h.submit('sign_in',_('Log In'),class_="btn btn-mini")}
344 ${h.submit('sign_in',_('Log In'),class_="btn btn-mini")}
345 </div>
345 </div>
346 </div>
346 </div>
347 </div>
347 </div>
348 </div>
348 </div>
349 ${h.end_form()}
349 ${h.end_form()}
350 %else:
350 %else:
351 <div class="links_left">
351 <div class="links_left">
352 <div class="big_gravatar"><img alt="gravatar" src="${h.gravatar_url(c.authuser.email,48)}" /></div>
352 <div class="big_gravatar"><img alt="gravatar" src="${h.gravatar_url(c.authuser.email,48)}" /></div>
353 <div class="full_name">${c.authuser.full_name_or_username}</div>
353 <div class="full_name">${c.authuser.full_name_or_username}</div>
354 <div class="email">${c.authuser.email}</div>
354 <div class="email">${c.authuser.email}</div>
355 </div>
355 </div>
356 <div class="links_right">
356 <div class="links_right">
357 <ol class="links">
357 <ol class="links">
358 <li><a href="${h.url('notifications')}">${_('Notifications')}: ${c.unread_notifications}</a></li>
358 <li><a href="${h.url('notifications')}">${_('Notifications')}: ${c.unread_notifications}</a></li>
359 <li>${h.link_to(_(u'My account'),h.url('my_account'))}</li>
359 <li>${h.link_to(_(u'My account'),h.url('my_account'))}</li>
360 <li class="logout">${h.link_to(_(u'Log Out'),h.url('logout_home'))}</li>
360 <li class="logout">${h.link_to(_(u'Log Out'),h.url('logout_home'))}</li>
361 </ol>
361 </ol>
362 </div>
362 </div>
363 %endif
363 %endif
364 </div>
364 </div>
365 </div>
365 </div>
366 </li>
366 </li>
367
367
368 <script type="text/javascript">
368 <script type="text/javascript">
369 var visual_show_public_icon = "${c.visual.show_public_icon}" == "True";
369 var visual_show_public_icon = "${c.visual.show_public_icon}" == "True";
370 var cache = {}
370 var cache = {}
371 /*format the look of items in the list*/
371 /*format the look of items in the list*/
372 var format = function(state){
372 var format = function(state){
373 if (!state.id){
373 if (!state.id){
374 return state.text; // optgroup
374 return state.text; // optgroup
375 }
375 }
376 var obj_dict = state.obj;
376 var obj_dict = state.obj;
377 var tmpl = '';
377 var tmpl = '';
378
378
379 if(obj_dict && state.type == 'repo'){
379 if(obj_dict && state.type == 'repo'){
380 tmpl += '<span class="repo-icons">';
380 tmpl += '<span class="repo-icons">';
381 if(obj_dict['repo_type'] === 'hg'){
381 if(obj_dict['repo_type'] === 'hg'){
382 tmpl += '<i class="icon-hg"></i> ';
382 tmpl += '<i class="icon-hg"></i> ';
383 }
383 }
384 else if(obj_dict['repo_type'] === 'git'){
384 else if(obj_dict['repo_type'] === 'git'){
385 tmpl += '<i class="icon-git"></i> ';
385 tmpl += '<i class="icon-git"></i> ';
386 }
386 }
387 if(obj_dict['private']){
387 if(obj_dict['private']){
388 tmpl += '<i class="icon-lock" style="color: #e85634;"></i> ';
388 tmpl += '<i class="icon-lock" style="color: #e85634;"></i> ';
389 }
389 }
390 else if(visual_show_public_icon){
390 else if(visual_show_public_icon){
391 tmpl += '<i class="icon-unlock-alt"></i> ';
391 tmpl += '<i class="icon-unlock-alt"></i> ';
392 }
392 }
393 tmpl += '</span>';
393 tmpl += '</span>';
394 }
394 }
395 if(obj_dict && state.type == 'group'){
395 if(obj_dict && state.type == 'group'){
396 tmpl += '<i class="icon-folder-close"></i> ';
396 tmpl += '<i class="icon-folder-close"></i> ';
397 }
397 }
398 tmpl += state.text;
398 tmpl += state.text;
399 return tmpl;
399 return tmpl;
400 }
400 }
401
401
402 $("#repo_switcher").select2({
402 $("#repo_switcher").select2({
403 placeholder: '<i class="icon-archive"></i> ${_('Repositories')}',
403 placeholder: '<i class="icon-archive"></i> ${_('Repositories')}',
404 dropdownAutoWidth: true,
404 dropdownAutoWidth: true,
405 formatResult: format,
405 formatResult: format,
406 formatSelection: format,
406 formatSelection: format,
407 formatNoMatches: function(term){
407 formatNoMatches: function(term){
408 return "${_('No matches found')}";
408 return "${_('No matches found')}";
409 },
409 },
410 containerCssClass: "repo-switcher",
410 containerCssClass: "repo-switcher",
411 dropdownCssClass: "repo-switcher-dropdown",
411 dropdownCssClass: "repo-switcher-dropdown",
412 escapeMarkup: function(m){
412 escapeMarkup: function(m){
413 // don't escape our custom placeholder
413 // don't escape our custom placeholder
414 if(m.substr(0,28) == '<i class="icon-archive"></i>'){
414 if(m.substr(0,28) == '<i class="icon-archive"></i>'){
415 return m;
415 return m;
416 }
416 }
417
417
418 return Select2.util.escapeMarkup(m);
418 return Select2.util.escapeMarkup(m);
419 },
419 },
420 query: function(query){
420 query: function(query){
421 var key = 'cache';
421 var key = 'cache';
422 var cached = cache[key] ;
422 var cached = cache[key] ;
423 if(cached) {
423 if(cached) {
424 var data = {results: []};
424 var data = {results: []};
425 //filter results
425 //filter results
426 $.each(cached.results, function(){
426 $.each(cached.results, function(){
427 var section = this.text;
427 var section = this.text;
428 var children = [];
428 var children = [];
429 $.each(this.children, function(){
429 $.each(this.children, function(){
430 if(query.term.length == 0 || this.text.toUpperCase().indexOf(query.term.toUpperCase()) >= 0 ){
430 if(query.term.length == 0 || this.text.toUpperCase().indexOf(query.term.toUpperCase()) >= 0 ){
431 children.push({'id': this.id, 'text': this.text, 'type': this.type, 'obj': this.obj})
431 children.push({'id': this.id, 'text': this.text, 'type': this.type, 'obj': this.obj})
432 }
432 }
433 })
433 })
434 if(children.length !== 0){
434 if(children.length !== 0){
435 data.results.push({'text': section, 'children': children})
435 data.results.push({'text': section, 'children': children})
436 }
436 }
437
437
438 });
438 });
439 query.callback(data);
439 query.callback(data);
440 }else{
440 }else{
441 $.ajax({
441 $.ajax({
442 url: "${h.url('repo_switcher_data')}",
442 url: "${h.url('repo_switcher_data')}",
443 data: {},
443 data: {},
444 dataType: 'json',
444 dataType: 'json',
445 type: 'GET',
445 type: 'GET',
446 success: function(data) {
446 success: function(data) {
447 cache[key] = data;
447 cache[key] = data;
448 query.callback({results: data.results});
448 query.callback({results: data.results});
449 }
449 }
450 })
450 })
451 }
451 }
452 },
452 }
453 });
453 });
454
454
455 $("#repo_switcher").on('select2-selecting', function(e){
455 $("#repo_switcher").on('select2-selecting', function(e){
456 e.preventDefault();
456 e.preventDefault();
457 window.location = pyroutes.url('summary_home', {'repo_name': e.val})
457 window.location = pyroutes.url('summary_home', {'repo_name': e.val})
458 })
458 })
459
459
460 ## Global mouse bindings ##
460 ## Global mouse bindings ##
461
461
462 // general help "?"
462 // general help "?"
463 Mousetrap.bind(['?'], function(e) {
463 Mousetrap.bind(['?'], function(e) {
464 $('#help_kb').modal({})
464 $('#help_kb').modal({})
465 });
465 });
466
466
467 // / open the quick filter
467 // / open the quick filter
468 Mousetrap.bind(['/'], function(e) {
468 Mousetrap.bind(['/'], function(e) {
469 $("#repo_switcher").select2("open");
469 $("#repo_switcher").select2("open");
470
470
471 // return false to prevent default browser behavior
471 // return false to prevent default browser behavior
472 // and stop event from bubbling
472 // and stop event from bubbling
473 return false;
473 return false;
474 });
474 });
475
475
476 // ctrl/command+b, show the the main bar
476 // ctrl/command+b, show the the main bar
477 Mousetrap.bind(['command+b', 'ctrl+b'], function(e) {
477 Mousetrap.bind(['command+b', 'ctrl+b'], function(e) {
478 if($('#header-inner').hasClass('hover') && $('#content').hasClass('hover')){
478 if($('#header-inner').hasClass('hover') && $('#content').hasClass('hover')){
479 $('#header-inner').removeClass('hover');
479 $('#header-inner').removeClass('hover');
480 $('#content').removeClass('hover');
480 $('#content').removeClass('hover');
481 }
481 }
482 else{
482 else{
483 $('#header-inner').addClass('hover');
483 $('#header-inner').addClass('hover');
484 $('#content').addClass('hover');
484 $('#content').addClass('hover');
485 }
485 }
486 return false;
486 return false;
487 });
487 });
488
488
489 // general nav g + action
489 // general nav g + action
490 Mousetrap.bind(['g h'], function(e) {
490 Mousetrap.bind(['g h'], function(e) {
491 window.location = pyroutes.url('home');
491 window.location = pyroutes.url('home');
492 });
492 });
493 Mousetrap.bind(['g g'], function(e) {
493 Mousetrap.bind(['g g'], function(e) {
494 window.location = pyroutes.url('gists', {'private':1});
494 window.location = pyroutes.url('gists', {'private':1});
495 });
495 });
496 Mousetrap.bind(['g G'], function(e) {
496 Mousetrap.bind(['g G'], function(e) {
497 window.location = pyroutes.url('gists', {'public':1});
497 window.location = pyroutes.url('gists', {'public':1});
498 });
498 });
499 Mousetrap.bind(['n g'], function(e) {
499 Mousetrap.bind(['n g'], function(e) {
500 window.location = pyroutes.url('new_gist');
500 window.location = pyroutes.url('new_gist');
501 });
501 });
502 Mousetrap.bind(['n r'], function(e) {
502 Mousetrap.bind(['n r'], function(e) {
503 window.location = pyroutes.url('new_repo');
503 window.location = pyroutes.url('new_repo');
504 });
504 });
505
505
506 % if hasattr(c, 'repo_name') and hasattr(c, 'db_repo'):
506 % if hasattr(c, 'repo_name') and hasattr(c, 'db_repo'):
507 // nav in repo context
507 // nav in repo context
508 Mousetrap.bind(['g s'], function(e) {
508 Mousetrap.bind(['g s'], function(e) {
509 window.location = pyroutes.url('summary_home', {'repo_name': REPO_NAME});
509 window.location = pyroutes.url('summary_home', {'repo_name': REPO_NAME});
510 });
510 });
511 Mousetrap.bind(['g c'], function(e) {
511 Mousetrap.bind(['g c'], function(e) {
512 window.location = pyroutes.url('changelog_home', {'repo_name': REPO_NAME});
512 window.location = pyroutes.url('changelog_home', {'repo_name': REPO_NAME});
513 });
513 });
514 Mousetrap.bind(['g F'], function(e) {
514 Mousetrap.bind(['g F'], function(e) {
515 window.location = pyroutes.url('files_home', {'repo_name': REPO_NAME, 'revision': '${c.db_repo.landing_rev[1]}', 'f_path': '', 'search': '1'});
515 window.location = pyroutes.url('files_home', {'repo_name': REPO_NAME, 'revision': '${c.db_repo.landing_rev[1]}', 'f_path': '', 'search': '1'});
516 });
516 });
517 Mousetrap.bind(['g f'], function(e) {
517 Mousetrap.bind(['g f'], function(e) {
518 window.location = pyroutes.url('files_home', {'repo_name': REPO_NAME, 'revision': '${c.db_repo.landing_rev[1]}', 'f_path': ''});
518 window.location = pyroutes.url('files_home', {'repo_name': REPO_NAME, 'revision': '${c.db_repo.landing_rev[1]}', 'f_path': ''});
519 });
519 });
520 Mousetrap.bind(['g o'], function(e) {
520 Mousetrap.bind(['g o'], function(e) {
521 window.location = pyroutes.url('edit_repo', {'repo_name': REPO_NAME});
521 window.location = pyroutes.url('edit_repo', {'repo_name': REPO_NAME});
522 });
522 });
523 Mousetrap.bind(['g O'], function(e) {
523 Mousetrap.bind(['g O'], function(e) {
524 window.location = pyroutes.url('edit_repo_perms', {'repo_name': REPO_NAME});
524 window.location = pyroutes.url('edit_repo_perms', {'repo_name': REPO_NAME});
525 });
525 });
526 % endif
526 % endif
527
527
528 </script>
528 </script>
529 </%def>
529 </%def>
530
530
531 %if 0:
531 %if 0:
532 <div class="modal" id="help_kb" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
532 <div class="modal" id="help_kb" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
533 <div class="modal-dialog">
533 <div class="modal-dialog">
534 <div class="modal-content">
534 <div class="modal-content">
535 <div class="modal-header">
535 <div class="modal-header">
536 <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
536 <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
537 <h4 class="modal-title">${_('Keyboard shortcuts')}</h4>
537 <h4 class="modal-title">${_('Keyboard shortcuts')}</h4>
538 </div>
538 </div>
539 <div class="modal-body">
539 <div class="modal-body">
540 <div class="row">
540 <div class="row">
541 <div class="col-md-5">
541 <div class="col-md-5">
542 <table class="keyboard-mappings">
542 <table class="keyboard-mappings">
543 <tbody>
543 <tbody>
544 <tr>
544 <tr>
545 <th></th>
545 <th></th>
546 <th>${_('Site-wide shortcuts')}</th>
546 <th>${_('Site-wide shortcuts')}</th>
547 </tr>
547 </tr>
548 <%
548 <%
549 elems = [
549 elems = [
550 ('/', 'Open quick search box'),
550 ('/', 'Open quick search box'),
551 ('ctrl/cmd+b', 'Show main settings bar'),
551 ('ctrl/cmd+b', 'Show main settings bar'),
552 ('g h', 'Goto home page'),
552 ('g h', 'Goto home page'),
553 ('g g', 'Goto my private gists page'),
553 ('g g', 'Goto my private gists page'),
554 ('g G', 'Goto my public gists page'),
554 ('g G', 'Goto my public gists page'),
555 ('n r', 'New repository page'),
555 ('n r', 'New repository page'),
556 ('n g', 'New gist page'),
556 ('n g', 'New gist page')
557 ]
557 ]
558 %>
558 %>
559 %for key, desc in elems:
559 %for key, desc in elems:
560 <tr>
560 <tr>
561 <td class="keys">
561 <td class="keys">
562 <span class="key">${key}</span>
562 <span class="key">${key}</span>
563 </td>
563 </td>
564 <td>${desc}</td>
564 <td>${desc}</td>
565 </tr>
565 </tr>
566 %endfor
566 %endfor
567 </tbody>
567 </tbody>
568 </table>
568 </table>
569 </div>
569 </div>
570 <div class="col-md-offset-5">
570 <div class="col-md-offset-5">
571 <table class="keyboard-mappings">
571 <table class="keyboard-mappings">
572 <tbody>
572 <tbody>
573 <tr>
573 <tr>
574 <th></th>
574 <th></th>
575 <th>${_('Repositories')}</th>
575 <th>${_('Repositories')}</th>
576 </tr>
576 </tr>
577 <%
577 <%
578 elems = [
578 elems = [
579 ('g s', 'Goto summary page'),
579 ('g s', 'Goto summary page'),
580 ('g c', 'Goto changelog page'),
580 ('g c', 'Goto changelog page'),
581 ('g f', 'Goto files page'),
581 ('g f', 'Goto files page'),
582 ('g F', 'Goto files page with file search activated'),
582 ('g F', 'Goto files page with file search activated'),
583 ('g o', 'Goto repository settings'),
583 ('g o', 'Goto repository settings'),
584 ('g O', 'Goto repository permissions settings'),
584 ('g O', 'Goto repository permissions settings')
585 ]
585 ]
586 %>
586 %>
587 %for key, desc in elems:
587 %for key, desc in elems:
588 <tr>
588 <tr>
589 <td class="keys">
589 <td class="keys">
590 <span class="key">${key}</span>
590 <span class="key">${key}</span>
591 </td>
591 </td>
592 <td>${desc}</td>
592 <td>${desc}</td>
593 </tr>
593 </tr>
594 %endfor
594 %endfor
595 </tbody>
595 </tbody>
596 </table>
596 </table>
597 </div>
597 </div>
598 </div>
598 </div>
599 </div>
599 </div>
600 <div class="modal-footer">
600 <div class="modal-footer">
601 </div>
601 </div>
602 </div><!-- /.modal-content -->
602 </div><!-- /.modal-content -->
603 </div><!-- /.modal-dialog -->
603 </div><!-- /.modal-dialog -->
604 </div><!-- /.modal -->
604 </div><!-- /.modal -->
605 %endif
605 %endif
@@ -1,142 +1,140 b''
1 ## -*- coding: utf-8 -*-
1 ## -*- coding: utf-8 -*-
2 <!DOCTYPE html>
2 <!DOCTYPE html>
3
3
4 <html xmlns="http://www.w3.org/1999/xhtml">
4 <html xmlns="http://www.w3.org/1999/xhtml">
5 <head>
5 <head>
6 <title>${self.title()}</title>
6 <title>${self.title()}</title>
7 <meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
7 <meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
8 <meta name="robots" content="index, nofollow"/>
8 <meta name="robots" content="index, nofollow"/>
9 <link rel="icon" href="${h.url('/images/favicon.ico')}" type="image/png" />
9 <link rel="icon" href="${h.url('/images/favicon.ico')}" type="image/png" />
10
10
11 ## CSS ###
11 ## CSS ###
12 <%def name="css()">
12 <%def name="css()">
13 <link rel="stylesheet" type="text/css" href="${h.url('/js/select2/select2.css', ver=c.kallithea_version)}"/>
13 <link rel="stylesheet" type="text/css" href="${h.url('/js/select2/select2.css', ver=c.kallithea_version)}"/>
14 <link rel="stylesheet" type="text/css" href="${h.url('/css/pygments.css', ver=c.kallithea_version)}"/>
14 <link rel="stylesheet" type="text/css" href="${h.url('/css/pygments.css', ver=c.kallithea_version)}"/>
15 <link rel="stylesheet" type="text/css" href="${h.url('/css/style.css', ver=c.kallithea_version)}" media="screen"/>
15 <link rel="stylesheet" type="text/css" href="${h.url('/css/style.css', ver=c.kallithea_version)}" media="screen"/>
16 <link rel="stylesheet" type="text/css" href="${h.url('/css/contextbar.css', ver=c.kallithea_version)}" media="screen"/>
16 <link rel="stylesheet" type="text/css" href="${h.url('/css/contextbar.css', ver=c.kallithea_version)}" media="screen"/>
17 ## EXTRA FOR CSS
17 ## EXTRA FOR CSS
18 ${self.css_extra()}
18 ${self.css_extra()}
19 </%def>
19 </%def>
20
20
21 <%def name="css_extra()"></%def>
21 <%def name="css_extra()"></%def>
22
22
23 ${self.css()}
23 ${self.css()}
24
24
25 ## JAVASCRIPT ##
25 ## JAVASCRIPT ##
26 <%def name="js()">
26 <%def name="js()">
27 <script type="text/javascript">
27 <script type="text/javascript">
28 //JS translations map
28 //JS translations map
29 var TRANSLATION_MAP = {
29 var TRANSLATION_MAP = {
30 'Add another comment':'${_("Add another comment")}',
30 'Add another comment':'${_("Add another comment")}',
31 'Stop following this repository':"${_('Stop following this repository')}",
31 'Stop following this repository':"${_('Stop following this repository')}",
32 'Start following this repository':"${_('Start following this repository')}",
32 'Start following this repository':"${_('Start following this repository')}",
33 'Group':"${_('Group')}",
33 'Group':"${_('Group')}",
34 'members':"${_('members')}",
34 'members':"${_('members')}",
35 'Loading ...':"${_('Loading ...')}",
35 'Loading ...':"${_('Loading ...')}",
36 'loading ...':"${_('loading ...')}",
36 'loading ...':"${_('loading ...')}",
37 'Search truncated': "${_('Search truncated')}",
37 'Search truncated': "${_('Search truncated')}",
38 'No matching files': "${_('No matching files')}",
38 'No matching files': "${_('No matching files')}",
39 'Open new pull request': "${_('Open new pull request')}",
39 'Open new pull request': "${_('Open new pull request')}",
40 'Open new pull request for selected changesets': "${_('Open new pull request for selected changesets')}",
40 'Open new pull request for selected changesets': "${_('Open new pull request for selected changesets')}",
41 'Show selected changesets __S &rarr; __E': "${h.literal(_('Show selected changesets __S &rarr; __E'))}",
41 'Show selected changesets __S &rarr; __E': "${h.literal(_('Show selected changesets __S &rarr; __E'))}",
42 'Show selected changeset __S': "${_('Show selected changeset __S')}",
42 'Show selected changeset __S': "${_('Show selected changeset __S')}",
43 'Selection link': "${_('Selection link')}",
43 'Selection link': "${_('Selection link')}",
44 'Collapse diff': "${_('Collapse diff')}",
44 'Collapse diff': "${_('Collapse diff')}",
45 'Expand diff': "${_('Expand diff')}",
45 'Expand diff': "${_('Expand diff')}",
46 'Failed to revoke permission': "${_('Failed to revoke permission')}",
46 'Failed to revoke permission': "${_('Failed to revoke permission')}",
47 'Confirm to revoke permission for {0}: {1} ?': "${_('confirm to revoke permission for {0}: {1} ?')}",
47 'Confirm to revoke permission for {0}: {1} ?': "${_('confirm to revoke permission for {0}: {1} ?')}",
48 'enabled': "${_('enabled')}",
48 'enabled': "${_('enabled')}",
49 'disabled': "${_('disabled')}",
49 'disabled': "${_('disabled')}",
50 'Select changeset': "${_('Select changeset')}",
50 'Select changeset': "${_('Select changeset')}",
51 'Specify changeset': "${_('Specify changeset')}",
51 'Specify changeset': "${_('Specify changeset')}",
52 'MSG_SORTASC': "${_('Click to sort ascending')}",
52 'MSG_SORTASC': "${_('Click to sort ascending')}",
53 'MSG_SORTDESC': "${_('Click to sort descending')}",
53 'MSG_SORTDESC': "${_('Click to sort descending')}",
54 'MSG_EMPTY': "${_('No records found.')}",
54 'MSG_EMPTY': "${_('No records found.')}",
55 'MSG_ERROR': "${_('Data error.')}",
55 'MSG_ERROR': "${_('Data error.')}",
56 'MSG_LOADING': "${_('Loading...')}",
56 'MSG_LOADING': "${_('Loading...')}"
57
58
59 };
57 };
60 var _TM = TRANSLATION_MAP;
58 var _TM = TRANSLATION_MAP;
61
59
62 var TOGGLE_FOLLOW_URL = "${h.url('toggle_following')}";
60 var TOGGLE_FOLLOW_URL = "${h.url('toggle_following')}";
63
61
64 var REPO_NAME = "";
62 var REPO_NAME = "";
65 %if hasattr(c, 'repo_name'):
63 %if hasattr(c, 'repo_name'):
66 var REPO_NAME = "${c.repo_name}";
64 var REPO_NAME = "${c.repo_name}";
67 %endif
65 %endif
68 </script>
66 </script>
69 <script type="text/javascript" src="${h.url('/js/yui.2.9.js', ver=c.kallithea_version)}"></script>
67 <script type="text/javascript" src="${h.url('/js/yui.2.9.js', ver=c.kallithea_version)}"></script>
70 <script type="text/javascript" src="${h.url('/js/jquery-1.10.2.min.js', ver=c.kallithea_version)}"></script>
68 <script type="text/javascript" src="${h.url('/js/jquery-1.10.2.min.js', ver=c.kallithea_version)}"></script>
71 <script type="text/javascript" src="${h.url('/js/bootstrap.js', ver=c.kallithea_version)}"></script>
69 <script type="text/javascript" src="${h.url('/js/bootstrap.js', ver=c.kallithea_version)}"></script>
72 <script type="text/javascript" src="${h.url('/js/select2/select2.js', ver=c.kallithea_version)}"></script>
70 <script type="text/javascript" src="${h.url('/js/select2/select2.js', ver=c.kallithea_version)}"></script>
73 <script type="text/javascript" src="${h.url('/js/mousetrap.js', ver=c.kallithea_version)}"></script>
71 <script type="text/javascript" src="${h.url('/js/mousetrap.js', ver=c.kallithea_version)}"></script>
74 <!--[if lt IE 9]>
72 <!--[if lt IE 9]>
75 <script language="javascript" type="text/javascript" src="${h.url('/js/excanvas.min.js')}"></script>
73 <script language="javascript" type="text/javascript" src="${h.url('/js/excanvas.min.js')}"></script>
76 <![endif]-->
74 <![endif]-->
77 <script type="text/javascript" src="${h.url('/js/yui.flot.js', ver=c.kallithea_version)}"></script>
75 <script type="text/javascript" src="${h.url('/js/yui.flot.js', ver=c.kallithea_version)}"></script>
78 <script type="text/javascript" src="${h.url('/js/native.history.js', ver=c.kallithea_version)}"></script>
76 <script type="text/javascript" src="${h.url('/js/native.history.js', ver=c.kallithea_version)}"></script>
79 <script type="text/javascript" src="${h.url('/js/pyroutes_map.js', ver=c.kallithea_version)}"></script>
77 <script type="text/javascript" src="${h.url('/js/pyroutes_map.js', ver=c.kallithea_version)}"></script>
80 <script type="text/javascript" src="${h.url('/js/base.js', ver=c.kallithea_version)}"></script>
78 <script type="text/javascript" src="${h.url('/js/base.js', ver=c.kallithea_version)}"></script>
81 ## EXTRA FOR JS
79 ## EXTRA FOR JS
82 ${self.js_extra()}
80 ${self.js_extra()}
83 <script type="text/javascript">
81 <script type="text/javascript">
84 (function(window,undefined){
82 (function(window,undefined){
85 // Prepare
83 // Prepare
86 var History = window.History; // Note: We are using a capital H instead of a lower h
84 var History = window.History; // Note: We are using a capital H instead of a lower h
87 if ( !History.enabled ) {
85 if ( !History.enabled ) {
88 // History.js is disabled for this browser.
86 // History.js is disabled for this browser.
89 // This is because we can optionally choose to support HTML4 browsers or not.
87 // This is because we can optionally choose to support HTML4 browsers or not.
90 return false;
88 return false;
91 }
89 }
92 })(window);
90 })(window);
93
91
94 $(document).ready(function(){
92 $(document).ready(function(){
95 tooltip_activate();
93 tooltip_activate();
96 show_more_event();
94 show_more_event();
97 show_changeset_tooltip();
95 show_changeset_tooltip();
98 // routes registration
96 // routes registration
99 pyroutes.register('home', "${h.url('home')}", []);
97 pyroutes.register('home', "${h.url('home')}", []);
100 pyroutes.register('new_gist', "${h.url('new_gist')}", []);
98 pyroutes.register('new_gist', "${h.url('new_gist')}", []);
101 pyroutes.register('gists', "${h.url('gists')}", []);
99 pyroutes.register('gists', "${h.url('gists')}", []);
102 pyroutes.register('new_repo', "${h.url('new_repo')}", []);
100 pyroutes.register('new_repo', "${h.url('new_repo')}", []);
103
101
104 pyroutes.register('summary_home', "${h.url('summary_home', repo_name='%(repo_name)s')}", ['repo_name']);
102 pyroutes.register('summary_home', "${h.url('summary_home', repo_name='%(repo_name)s')}", ['repo_name']);
105 pyroutes.register('changelog_home', "${h.url('changelog_home', repo_name='%(repo_name)s')}", ['repo_name']);
103 pyroutes.register('changelog_home', "${h.url('changelog_home', repo_name='%(repo_name)s')}", ['repo_name']);
106 pyroutes.register('files_home', "${h.url('files_home', repo_name='%(repo_name)s',revision='%(revision)s',f_path='%(f_path)s')}", ['repo_name', 'revision', 'f_path']);
104 pyroutes.register('files_home', "${h.url('files_home', repo_name='%(repo_name)s',revision='%(revision)s',f_path='%(f_path)s')}", ['repo_name', 'revision', 'f_path']);
107 pyroutes.register('edit_repo', "${h.url('edit_repo', repo_name='%(repo_name)s')}", ['repo_name']);
105 pyroutes.register('edit_repo', "${h.url('edit_repo', repo_name='%(repo_name)s')}", ['repo_name']);
108 pyroutes.register('edit_repo_perms', "${h.url('edit_repo_perms', repo_name='%(repo_name)s')}", ['repo_name']);
106 pyroutes.register('edit_repo_perms', "${h.url('edit_repo_perms', repo_name='%(repo_name)s')}", ['repo_name']);
109 pyroutes.register('pullrequest_home', "${h.url('pullrequest_home', repo_name='%(repo_name)s')}", ['repo_name']);
107 pyroutes.register('pullrequest_home', "${h.url('pullrequest_home', repo_name='%(repo_name)s')}", ['repo_name']);
110
108
111 pyroutes.register('toggle_following', "${h.url('toggle_following')}");
109 pyroutes.register('toggle_following', "${h.url('toggle_following')}");
112 pyroutes.register('changeset_info', "${h.url('changeset_info', repo_name='%(repo_name)s', revision='%(revision)s')}", ['repo_name', 'revision']);
110 pyroutes.register('changeset_info', "${h.url('changeset_info', repo_name='%(repo_name)s', revision='%(revision)s')}", ['repo_name', 'revision']);
113 pyroutes.register('repo_size', "${h.url('repo_size', repo_name='%(repo_name)s')}", ['repo_name']);
111 pyroutes.register('repo_size', "${h.url('repo_size', repo_name='%(repo_name)s')}", ['repo_name']);
114 pyroutes.register('changeset_comment_preview', "${h.url('changeset_comment_preview', repo_name='%(repo_name)s')}", ['repo_name']);
112 pyroutes.register('changeset_comment_preview', "${h.url('changeset_comment_preview', repo_name='%(repo_name)s')}", ['repo_name']);
115 pyroutes.register('repo_refs_data', "${h.url('repo_refs_data', repo_name='%(repo_name)s')}", ['repo_name']);
113 pyroutes.register('repo_refs_data', "${h.url('repo_refs_data', repo_name='%(repo_name)s')}", ['repo_name']);
116 });
114 });
117 </script>
115 </script>
118 </%def>
116 </%def>
119 <%def name="js_extra()"></%def>
117 <%def name="js_extra()"></%def>
120 ${self.js()}
118 ${self.js()}
121 <%def name="head_extra()"></%def>
119 <%def name="head_extra()"></%def>
122 ${self.head_extra()}
120 ${self.head_extra()}
123 </head>
121 </head>
124 <body id="body">
122 <body id="body">
125 ## IE hacks
123 ## IE hacks
126 <!--[if IE 7]>
124 <!--[if IE 7]>
127 <script>$(document.body).addClass('ie7')</script>
125 <script>$(document.body).addClass('ie7')</script>
128 <![endif]-->
126 <![endif]-->
129 <!--[if IE 8]>
127 <!--[if IE 8]>
130 <script>$(document.body).addClass('ie8')</script>
128 <script>$(document.body).addClass('ie8')</script>
131 <![endif]-->
129 <![endif]-->
132 <!--[if IE 9]>
130 <!--[if IE 9]>
133 <script>$(document.body).addClass('ie9')</script>
131 <script>$(document.body).addClass('ie9')</script>
134 <![endif]-->
132 <![endif]-->
135
133
136 ${next.body()}
134 ${next.body()}
137
135
138 %if c.ga_code:
136 %if c.ga_code:
139 ${h.literal(c.ga_code)}
137 ${h.literal(c.ga_code)}
140 %endif
138 %endif
141 </body>
139 </body>
142 </html>
140 </html>
@@ -1,99 +1,99 b''
1 ## -*- coding: utf-8 -*-
1 ## -*- coding: utf-8 -*-
2 <%inherit file="/base/base.html"/>
2 <%inherit file="/base/base.html"/>
3
3
4 <%def name="title()">
4 <%def name="title()">
5 ${_('%s Bookmarks') % c.repo_name}
5 ${_('%s Bookmarks') % c.repo_name}
6 %if c.site_name:
6 %if c.site_name:
7 &middot; ${c.site_name}
7 &middot; ${c.site_name}
8 %endif
8 %endif
9 </%def>
9 </%def>
10
10
11 <%def name="breadcrumbs_links()">
11 <%def name="breadcrumbs_links()">
12 <input class="q_filter_box" id="q_filter_bookmarks" size="15" type="text" name="filter" placeholder="${_('quick filter...')}" value=""/>
12 <input class="q_filter_box" id="q_filter_bookmarks" size="15" type="text" name="filter" placeholder="${_('quick filter...')}" value=""/>
13 ${_('Bookmarks')}
13 ${_('Bookmarks')}
14 </%def>
14 </%def>
15
15
16 <%def name="page_nav()">
16 <%def name="page_nav()">
17 ${self.menu('repositories')}
17 ${self.menu('repositories')}
18 </%def>
18 </%def>
19
19
20 <%def name="main()">
20 <%def name="main()">
21 ${self.repo_context_bar('switch-to')}
21 ${self.repo_context_bar('switch-to')}
22 <div class="box">
22 <div class="box">
23 <!-- box / title -->
23 <!-- box / title -->
24 <div class="title">
24 <div class="title">
25 ${self.breadcrumbs()}
25 ${self.breadcrumbs()}
26 </div>
26 </div>
27 <!-- end box / title -->
27 <!-- end box / title -->
28 %if c.repo_bookmarks:
28 %if c.repo_bookmarks:
29 <div class="info_box" id="compare_bookmarks" style="clear: both;padding: 10px 19px;text-align: right;"><a href="#" class="btn btn-mini">${_('Compare Bookmarks')}</a></div>
29 <div class="info_box" id="compare_bookmarks" style="clear: both;padding: 10px 19px;text-align: right;"><a href="#" class="btn btn-mini">${_('Compare Bookmarks')}</a></div>
30 %endif
30 %endif
31 <div class="table">
31 <div class="table">
32 <%include file='bookmarks_data.html'/>
32 <%include file='bookmarks_data.html'/>
33 </div>
33 </div>
34 </div>
34 </div>
35
35
36 <script type="text/javascript">
36 <script type="text/javascript">
37 YUE.on('compare_bookmarks','click',function(e){
37 YUE.on('compare_bookmarks','click',function(e){
38 YUE.preventDefault(e);
38 YUE.preventDefault(e);
39 var org = YUQ('input[name=compare_org]:checked')[0];
39 var org = YUQ('input[name=compare_org]:checked')[0];
40 var other = YUQ('input[name=compare_other]:checked')[0];
40 var other = YUQ('input[name=compare_other]:checked')[0];
41
41
42 if(org && other){
42 if(org && other){
43 var compare_url = "${h.url('compare_url',repo_name=c.repo_name,org_ref_type='book',org_ref_name='__ORG__',other_ref_type='book',other_ref_name='__OTHER__')}";
43 var compare_url = "${h.url('compare_url',repo_name=c.repo_name,org_ref_type='book',org_ref_name='__ORG__',other_ref_type='book',other_ref_name='__OTHER__')}";
44 var u = compare_url.replace('__ORG__',org.value)
44 var u = compare_url.replace('__ORG__',org.value)
45 .replace('__OTHER__',other.value);
45 .replace('__OTHER__',other.value);
46 window.location=u;
46 window.location=u;
47 }
47 }
48 });
48 });
49 // main table sorting
49 // main table sorting
50 var myColumnDefs = [
50 var myColumnDefs = [
51 {key:"name",label:"${_('Name')}",sortable:true,
51 {key:"name",label:"${_('Name')}",sortable:true,
52 sortOptions: { sortFunction: nameSort }},
52 sortOptions: { sortFunction: nameSort }},
53 {key:"date",label:"${_('Date')}",sortable:true,
53 {key:"date",label:"${_('Date')}",sortable:true,
54 sortOptions: { sortFunction: dateSort }},
54 sortOptions: { sortFunction: dateSort }},
55 {key:"author",label:"${_('Author')}",sortable:true},
55 {key:"author",label:"${_('Author')}",sortable:true},
56 {key:"revision",label:"${_('Revision')}",sortable:true,
56 {key:"revision",label:"${_('Revision')}",sortable:true,
57 sortOptions: { sortFunction: revisionSort }},
57 sortOptions: { sortFunction: revisionSort }},
58 {key:"compare",label:"${_('Compare')}",sortable:false,},
58 {key:"compare",label:"${_('Compare')}",sortable:false}
59 ];
59 ];
60
60
61 var myDataSource = new YAHOO.util.DataSource(YUD.get("bookmarks_data"));
61 var myDataSource = new YAHOO.util.DataSource(YUD.get("bookmarks_data"));
62
62
63 myDataSource.responseType = YAHOO.util.DataSource.TYPE_HTMLTABLE;
63 myDataSource.responseType = YAHOO.util.DataSource.TYPE_HTMLTABLE;
64
64
65 myDataSource.responseSchema = {
65 myDataSource.responseSchema = {
66 fields: [
66 fields: [
67 {key:"raw_name"},
67 {key:"raw_name"},
68 {key:"name"},
68 {key:"name"},
69 {key:"raw_date"},
69 {key:"raw_date"},
70 {key:"date"},
70 {key:"date"},
71 {key:"author"},
71 {key:"author"},
72 {key:"last_rev_raw"},
72 {key:"last_rev_raw"},
73 {key:"revision"},
73 {key:"revision"},
74 {key:"compare"},
74 {key:"compare"}
75 ]
75 ]
76 };
76 };
77
77
78 var myDataTable = new YAHOO.widget.DataTable("table_wrap", myColumnDefs, myDataSource,
78 var myDataTable = new YAHOO.widget.DataTable("table_wrap", myColumnDefs, myDataSource,
79 {
79 {
80 sortedBy:{key:"name",dir:"asc"},
80 sortedBy:{key:"name",dir:"asc"},
81 MSG_SORTASC:"${_('Click to sort ascending')}",
81 MSG_SORTASC:"${_('Click to sort ascending')}",
82 MSG_SORTDESC:"${_('Click to sort descending')}",
82 MSG_SORTDESC:"${_('Click to sort descending')}",
83 MSG_EMPTY:"${_('No records found.')}",
83 MSG_EMPTY:"${_('No records found.')}",
84 MSG_ERROR:"${_('Data error.')}",
84 MSG_ERROR:"${_('Data error.')}",
85 MSG_LOADING:"${_('Loading...')}",
85 MSG_LOADING:"${_('Loading...')}"
86 }
86 }
87 );
87 );
88 myDataTable.subscribe('postRenderEvent',function(oArgs) {
88 myDataTable.subscribe('postRenderEvent',function(oArgs) {
89 tooltip_activate();
89 tooltip_activate();
90 var func = function(node){
90 var func = function(node){
91 return node.parentNode.parentNode.parentNode.parentNode.parentNode;
91 return node.parentNode.parentNode.parentNode.parentNode.parentNode;
92 }
92 }
93 q_filter('q_filter_bookmarks',YUQ('div.table tr td .logbooks .booktag a'),func);
93 q_filter('q_filter_bookmarks',YUQ('div.table tr td .logbooks .booktag a'),func);
94 });
94 });
95
95
96 </script>
96 </script>
97
97
98
98
99 </%def>
99 </%def>
@@ -1,97 +1,97 b''
1 ## -*- coding: utf-8 -*-
1 ## -*- coding: utf-8 -*-
2 <%inherit file="/base/base.html"/>
2 <%inherit file="/base/base.html"/>
3
3
4 <%def name="title()">
4 <%def name="title()">
5 ${_('%s Branches') % c.repo_name}
5 ${_('%s Branches') % c.repo_name}
6 %if c.site_name:
6 %if c.site_name:
7 &middot; ${c.site_name}
7 &middot; ${c.site_name}
8 %endif
8 %endif
9 </%def>
9 </%def>
10
10
11 <%def name="breadcrumbs_links()">
11 <%def name="breadcrumbs_links()">
12 <input class="q_filter_box" id="q_filter_branches" size="15" type="text" name="filter" placeholder="${_('quick filter...')}" value=""/>
12 <input class="q_filter_box" id="q_filter_branches" size="15" type="text" name="filter" placeholder="${_('quick filter...')}" value=""/>
13 ${_('Branches')}
13 ${_('Branches')}
14 </%def>
14 </%def>
15
15
16 <%def name="page_nav()">
16 <%def name="page_nav()">
17 ${self.menu('repositories')}
17 ${self.menu('repositories')}
18 </%def>
18 </%def>
19
19
20 <%def name="main()">
20 <%def name="main()">
21 ${self.repo_context_bar('switch-to')}
21 ${self.repo_context_bar('switch-to')}
22 <div class="box">
22 <div class="box">
23 <!-- box / title -->
23 <!-- box / title -->
24 <div class="title">
24 <div class="title">
25 ${self.breadcrumbs()}
25 ${self.breadcrumbs()}
26 </div>
26 </div>
27 <!-- end box / title -->
27 <!-- end box / title -->
28 %if c.repo_branches:
28 %if c.repo_branches:
29 <div class="info_box" id="compare_branches" style="clear: both;padding: 10px 19px;text-align: right;"><a href="#" class="btn btn-mini">${_('Compare Branches')}</a></div>
29 <div class="info_box" id="compare_branches" style="clear: both;padding: 10px 19px;text-align: right;"><a href="#" class="btn btn-mini">${_('Compare Branches')}</a></div>
30 %endif
30 %endif
31 <div class="table">
31 <div class="table">
32 <%include file='branches_data.html'/>
32 <%include file='branches_data.html'/>
33 </div>
33 </div>
34 </div>
34 </div>
35 <script type="text/javascript">
35 <script type="text/javascript">
36 YUE.on('compare_branches','click',function(e){
36 YUE.on('compare_branches','click',function(e){
37 YUE.preventDefault(e);
37 YUE.preventDefault(e);
38 var org = YUQ('input[name=compare_org]:checked')[0];
38 var org = YUQ('input[name=compare_org]:checked')[0];
39 var other = YUQ('input[name=compare_other]:checked')[0];
39 var other = YUQ('input[name=compare_other]:checked')[0];
40
40
41 if(org && other){
41 if(org && other){
42 var compare_url = "${h.url('compare_url',repo_name=c.repo_name,org_ref_type='branch',org_ref_name='__ORG__',other_ref_type='branch',other_ref_name='__OTHER__')}";
42 var compare_url = "${h.url('compare_url',repo_name=c.repo_name,org_ref_type='branch',org_ref_name='__ORG__',other_ref_type='branch',other_ref_name='__OTHER__')}";
43 var u = compare_url.replace('__ORG__',org.value)
43 var u = compare_url.replace('__ORG__',org.value)
44 .replace('__OTHER__',other.value);
44 .replace('__OTHER__',other.value);
45 window.location=u;
45 window.location=u;
46 }
46 }
47 });
47 });
48 // main table sorting
48 // main table sorting
49 var myColumnDefs = [
49 var myColumnDefs = [
50 {key:"name",label:"${_('Name')}",sortable:true,
50 {key:"name",label:"${_('Name')}",sortable:true,
51 sortOptions: { sortFunction: nameSort }},
51 sortOptions: { sortFunction: nameSort }},
52 {key:"date",label:"${_('Date')}",sortable:true,
52 {key:"date",label:"${_('Date')}",sortable:true,
53 sortOptions: { sortFunction: dateSort }},
53 sortOptions: { sortFunction: dateSort }},
54 {key:"author",label:"${_('Author')}",sortable:true},
54 {key:"author",label:"${_('Author')}",sortable:true},
55 {key:"revision",label:"${_('Revision')}",sortable:true,
55 {key:"revision",label:"${_('Revision')}",sortable:true,
56 sortOptions: { sortFunction: revisionSort }},
56 sortOptions: { sortFunction: revisionSort }},
57 {key:"compare",label:"${_('Compare')}",sortable:false,},
57 {key:"compare",label:"${_('Compare')}",sortable:false}
58 ];
58 ];
59
59
60 var myDataSource = new YAHOO.util.DataSource(YUD.get("branches_data"));
60 var myDataSource = new YAHOO.util.DataSource(YUD.get("branches_data"));
61
61
62 myDataSource.responseType = YAHOO.util.DataSource.TYPE_HTMLTABLE;
62 myDataSource.responseType = YAHOO.util.DataSource.TYPE_HTMLTABLE;
63
63
64 myDataSource.responseSchema = {
64 myDataSource.responseSchema = {
65 fields: [
65 fields: [
66 {key:"raw_name"},
66 {key:"raw_name"},
67 {key:"name"},
67 {key:"name"},
68 {key:"raw_date"},
68 {key:"raw_date"},
69 {key:"date"},
69 {key:"date"},
70 {key:"author"},
70 {key:"author"},
71 {key:"last_rev_raw"},
71 {key:"last_rev_raw"},
72 {key:"revision"},
72 {key:"revision"},
73 {key:"compare"},
73 {key:"compare"}
74 ]
74 ]
75 };
75 };
76
76
77 var myDataTable = new YAHOO.widget.DataTable("table_wrap", myColumnDefs, myDataSource,
77 var myDataTable = new YAHOO.widget.DataTable("table_wrap", myColumnDefs, myDataSource,
78 {
78 {
79 sortedBy:{key:"name",dir:"asc"},
79 sortedBy:{key:"name",dir:"asc"},
80 MSG_SORTASC:"${_('Click to sort ascending')}",
80 MSG_SORTASC:"${_('Click to sort ascending')}",
81 MSG_SORTDESC:"${_('Click to sort descending')}",
81 MSG_SORTDESC:"${_('Click to sort descending')}",
82 MSG_EMPTY:"${_('No records found.')}",
82 MSG_EMPTY:"${_('No records found.')}",
83 MSG_ERROR:"${_('Data error.')}",
83 MSG_ERROR:"${_('Data error.')}",
84 MSG_LOADING:"${_('Loading...')}",
84 MSG_LOADING:"${_('Loading...')}"
85 }
85 }
86 );
86 );
87 myDataTable.subscribe('postRenderEvent',function(oArgs) {
87 myDataTable.subscribe('postRenderEvent',function(oArgs) {
88 tooltip_activate();
88 tooltip_activate();
89 var func = function(node){
89 var func = function(node){
90 return node.parentNode.parentNode.parentNode.parentNode.parentNode;
90 return node.parentNode.parentNode.parentNode.parentNode.parentNode;
91 }
91 }
92 q_filter('q_filter_branches',YUQ('div.table tr td .logtags .branchtag a'),func);
92 q_filter('q_filter_branches',YUQ('div.table tr td .logtags .branchtag a'),func);
93 });
93 });
94
94
95 </script>
95 </script>
96
96
97 </%def>
97 </%def>
@@ -1,298 +1,298 b''
1 ## -*- coding: utf-8 -*-
1 ## -*- coding: utf-8 -*-
2
2
3 <%inherit file="/base/base.html"/>
3 <%inherit file="/base/base.html"/>
4
4
5 <%def name="title()">
5 <%def name="title()">
6 ${_('%s Changelog') % c.repo_name}
6 ${_('%s Changelog') % c.repo_name}
7 %if c.changelog_for_path:
7 %if c.changelog_for_path:
8 /${c.changelog_for_path}
8 /${c.changelog_for_path}
9 %endif
9 %endif
10 %if c.site_name:
10 %if c.site_name:
11 &middot; ${c.site_name}
11 &middot; ${c.site_name}
12 %endif
12 %endif
13 </%def>
13 </%def>
14
14
15 <%def name="breadcrumbs_links()">
15 <%def name="breadcrumbs_links()">
16 <% size = c.size if c.size <= c.total_cs else c.total_cs %>
16 <% size = c.size if c.size <= c.total_cs else c.total_cs %>
17 ${_('Changelog')}
17 ${_('Changelog')}
18 %if c.changelog_for_path:
18 %if c.changelog_for_path:
19 - /${c.changelog_for_path}
19 - /${c.changelog_for_path}
20 %endif
20 %endif
21 %if c.revision:
21 %if c.revision:
22 @ ${h.short_id(c.first_revision.raw_id)}
22 @ ${h.short_id(c.first_revision.raw_id)}
23 %endif
23 %endif
24 - ${ungettext('showing %d out of %d revision', 'showing %d out of %d revisions', size) % (size, c.total_cs)}
24 - ${ungettext('showing %d out of %d revision', 'showing %d out of %d revisions', size) % (size, c.total_cs)}
25 </%def>
25 </%def>
26
26
27 <%def name="page_nav()">
27 <%def name="page_nav()">
28 ${self.menu('repositories')}
28 ${self.menu('repositories')}
29 </%def>
29 </%def>
30
30
31 <%def name="main()">
31 <%def name="main()">
32 ${self.repo_context_bar('changelog', c.first_revision.raw_id if c.first_revision else None)}
32 ${self.repo_context_bar('changelog', c.first_revision.raw_id if c.first_revision else None)}
33 <div class="box">
33 <div class="box">
34 <!-- box / title -->
34 <!-- box / title -->
35 <div class="title">
35 <div class="title">
36 ${self.breadcrumbs()}
36 ${self.breadcrumbs()}
37 </div>
37 </div>
38 <div class="table">
38 <div class="table">
39 % if c.pagination:
39 % if c.pagination:
40 <div>
40 <div>
41 <div style="overflow:auto; display:${'none' if c.changelog_for_path else ''}">
41 <div style="overflow:auto; display:${'none' if c.changelog_for_path else ''}">
42 <div class="container_header">
42 <div class="container_header">
43 <div style="float:left; margin-left:20px;">
43 <div style="float:left; margin-left:20px;">
44 ${h.form(h.url.current(),method='get')}
44 ${h.form(h.url.current(),method='get')}
45 ${h.submit('set',_('Show'),class_="btn btn-small")}
45 ${h.submit('set',_('Show'),class_="btn btn-small")}
46 ${h.text('size',size=3,value=c.size)}
46 ${h.text('size',size=3,value=c.size)}
47 ${_('revisions')}
47 ${_('revisions')}
48 %if c.branch_name:
48 %if c.branch_name:
49 ${h.hidden('branch', c.branch_name)}
49 ${h.hidden('branch', c.branch_name)}
50 %endif
50 %endif
51 ${h.end_form()}
51 ${h.end_form()}
52 </div>
52 </div>
53 <div style="float: right; margin: 0px 0px 0px 4px">
53 <div style="float: right; margin: 0px 0px 0px 4px">
54 <a href="#" class="btn btn-small" id="rev_range_container" style="display:none"></a>
54 <a href="#" class="btn btn-small" id="rev_range_container" style="display:none"></a>
55 <a href="#" class="btn btn-small" id="rev_range_clear" style="display:none">${_('Clear selection')}</a>
55 <a href="#" class="btn btn-small" id="rev_range_clear" style="display:none">${_('Clear selection')}</a>
56 %if c.revision:
56 %if c.revision:
57 <a class="btn btn-small" href="${h.url('changelog_home', repo_name=c.repo_name)}">
57 <a class="btn btn-small" href="${h.url('changelog_home', repo_name=c.repo_name)}">
58 ${_('Go to tip of repository')}
58 ${_('Go to tip of repository')}
59 </a>
59 </a>
60 %endif
60 %endif
61 %if c.db_repo.fork:
61 %if c.db_repo.fork:
62 <a id="compare_fork"
62 <a id="compare_fork"
63 title="${_('Compare fork with %s' % c.db_repo.fork.repo_name)}"
63 title="${_('Compare fork with %s' % c.db_repo.fork.repo_name)}"
64 href="${h.url('compare_url',repo_name=c.db_repo.fork.repo_name,org_ref_type=c.db_repo.landing_rev[0],org_ref_name=c.db_repo.landing_rev[1],other_repo=c.repo_name,other_ref_type='branch' if request.GET.get('branch') else c.db_repo.landing_rev[0],other_ref_name=request.GET.get('branch') or c.db_repo.landing_rev[1], merge=1)}"
64 href="${h.url('compare_url',repo_name=c.db_repo.fork.repo_name,org_ref_type=c.db_repo.landing_rev[0],org_ref_name=c.db_repo.landing_rev[1],other_repo=c.repo_name,other_ref_type='branch' if request.GET.get('branch') else c.db_repo.landing_rev[0],other_ref_name=request.GET.get('branch') or c.db_repo.landing_rev[1], merge=1)}"
65 class="btn btn-small"><i class="icon-loop"></i> ${_('Compare fork with parent repo (%s)' % c.db_repo.fork.repo_name)}</a>
65 class="btn btn-small"><i class="icon-loop"></i> ${_('Compare fork with parent repo (%s)' % c.db_repo.fork.repo_name)}</a>
66 %endif
66 %endif
67 ## text and href of open_new_pr is controlled from javascript
67 ## text and href of open_new_pr is controlled from javascript
68 <a id="open_new_pr" class="btn btn-small"></a>
68 <a id="open_new_pr" class="btn btn-small"></a>
69 ${_("Branch filter:")} ${h.select('branch_filter',c.branch_name,c.branch_filters)}
69 ${_("Branch filter:")} ${h.select('branch_filter',c.branch_name,c.branch_filters)}
70 </div>
70 </div>
71 </div>
71 </div>
72 </div>
72 </div>
73
73
74 <div id="changelog" style="clear:both">
74 <div id="changelog" style="clear:both">
75
75
76 <div id="graph_nodes">
76 <div id="graph_nodes">
77 <canvas id="graph_canvas"></canvas>
77 <canvas id="graph_canvas"></canvas>
78 </div>
78 </div>
79 <div id="graph_content" style="${'margin: 0px' if c.changelog_for_path else ''}">
79 <div id="graph_content" style="${'margin: 0px' if c.changelog_for_path else ''}">
80
80
81 <table id="changesets">
81 <table id="changesets">
82 <tbody>
82 <tbody>
83 %for cnt,cs in enumerate(c.pagination):
83 %for cnt,cs in enumerate(c.pagination):
84 <tr id="chg_${cnt+1}" class="container ${'tablerow%s' % (cnt%2)}">
84 <tr id="chg_${cnt+1}" class="container ${'tablerow%s' % (cnt%2)}">
85 <td class="checkbox">
85 <td class="checkbox">
86 %if c.changelog_for_path:
86 %if c.changelog_for_path:
87 ${h.checkbox(cs.raw_id,class_="changeset_range", disabled="disabled")}
87 ${h.checkbox(cs.raw_id,class_="changeset_range", disabled="disabled")}
88 %else:
88 %else:
89 ${h.checkbox(cs.raw_id,class_="changeset_range")}
89 ${h.checkbox(cs.raw_id,class_="changeset_range")}
90 %endif
90 %endif
91 <td class="status">
91 <td class="status">
92 %if c.statuses.get(cs.raw_id):
92 %if c.statuses.get(cs.raw_id):
93 <div class="changeset-status-ico">
93 <div class="changeset-status-ico">
94 %if c.statuses.get(cs.raw_id)[2]:
94 %if c.statuses.get(cs.raw_id)[2]:
95 <a class="tooltip" title="${_('Changeset status: %s\nClick to open associated pull request #%s') % (h.changeset_status_lbl(c.statuses.get(cs.raw_id)[0]), c.statuses.get(cs.raw_id)[2])}" href="${h.url('pullrequest_show',repo_name=c.statuses.get(cs.raw_id)[3],pull_request_id=c.statuses.get(cs.raw_id)[2])}">
95 <a class="tooltip" title="${_('Changeset status: %s\nClick to open associated pull request #%s') % (h.changeset_status_lbl(c.statuses.get(cs.raw_id)[0]), c.statuses.get(cs.raw_id)[2])}" href="${h.url('pullrequest_show',repo_name=c.statuses.get(cs.raw_id)[3],pull_request_id=c.statuses.get(cs.raw_id)[2])}">
96 <img src="${h.url('/images/icons/flag_status_%s.png' % c.statuses.get(cs.raw_id)[0])}" />
96 <img src="${h.url('/images/icons/flag_status_%s.png' % c.statuses.get(cs.raw_id)[0])}" />
97 </a>
97 </a>
98 %else:
98 %else:
99 <a class="tooltip" title="${_('Changeset status: %s') % h.changeset_status_lbl(c.statuses.get(cs.raw_id)[0])}" href="${h.url('changeset_home',repo_name=c.repo_name,revision=cs.raw_id,anchor='comment-%s' % c.comments[cs.raw_id][0].comment_id)}">
99 <a class="tooltip" title="${_('Changeset status: %s') % h.changeset_status_lbl(c.statuses.get(cs.raw_id)[0])}" href="${h.url('changeset_home',repo_name=c.repo_name,revision=cs.raw_id,anchor='comment-%s' % c.comments[cs.raw_id][0].comment_id)}">
100 <img src="${h.url('/images/icons/flag_status_%s.png' % c.statuses.get(cs.raw_id)[0])}" />
100 <img src="${h.url('/images/icons/flag_status_%s.png' % c.statuses.get(cs.raw_id)[0])}" />
101 </a>
101 </a>
102 %endif
102 %endif
103 </div>
103 </div>
104 %endif
104 %endif
105 </td>
105 </td>
106 <td class="author">
106 <td class="author">
107 <img alt="gravatar" src="${h.gravatar_url(h.email_or_none(cs.author),16)}"/>
107 <img alt="gravatar" src="${h.gravatar_url(h.email_or_none(cs.author),16)}"/>
108 <span title="${cs.author}" class="user">${h.shorter(h.person(cs.author),22)}</span>
108 <span title="${cs.author}" class="user">${h.shorter(h.person(cs.author),22)}</span>
109 </td>
109 </td>
110 <td class="hash" style="width:${len(h.show_id(cs))*6.5}px">
110 <td class="hash" style="width:${len(h.show_id(cs))*6.5}px">
111 <a href="${h.url('changeset_home',repo_name=c.repo_name,revision=cs.raw_id)}">
111 <a href="${h.url('changeset_home',repo_name=c.repo_name,revision=cs.raw_id)}">
112 <span class="changeset_hash">${h.show_id(cs)}</span>
112 <span class="changeset_hash">${h.show_id(cs)}</span>
113 </a>
113 </a>
114 </td>
114 </td>
115 <td class="date">
115 <td class="date">
116 <div class="date">${h.age(cs.date,True)}</div>
116 <div class="date">${h.age(cs.date,True)}</div>
117 </td>
117 </td>
118 <td class="expand_commit" commit_id="${cs.raw_id}" title="${_('Expand commit message')}">
118 <td class="expand_commit" commit_id="${cs.raw_id}" title="${_('Expand commit message')}">
119 <i class="icon-resize-vertical" style="color:#DDD"></i>
119 <i class="icon-resize-vertical" style="color:#DDD"></i>
120 </td>
120 </td>
121 <td class="mid">
121 <td class="mid">
122 <div class="log-container">
122 <div class="log-container">
123 <div class="message" id="C-${cs.raw_id}">${h.urlify_commit(cs.message, c.repo_name,h.url('changeset_home',repo_name=c.repo_name,revision=cs.raw_id))}</div>
123 <div class="message" id="C-${cs.raw_id}">${h.urlify_commit(cs.message, c.repo_name,h.url('changeset_home',repo_name=c.repo_name,revision=cs.raw_id))}</div>
124 <div class="extra-container">
124 <div class="extra-container">
125 %if c.comments.get(cs.raw_id):
125 %if c.comments.get(cs.raw_id):
126 <div class="comments-container">
126 <div class="comments-container">
127 <div class="comments-cnt" title="${_('Changeset has comments')}">
127 <div class="comments-cnt" title="${_('Changeset has comments')}">
128 <a href="${h.url('changeset_home',repo_name=c.repo_name,revision=cs.raw_id,anchor='comment-%s' % c.comments[cs.raw_id][0].comment_id)}">
128 <a href="${h.url('changeset_home',repo_name=c.repo_name,revision=cs.raw_id,anchor='comment-%s' % c.comments[cs.raw_id][0].comment_id)}">
129 ${len(c.comments[cs.raw_id])}
129 ${len(c.comments[cs.raw_id])}
130 <i class="icon-comment-alt icon-comment-colored"></i>
130 <i class="icon-comment-alt icon-comment-colored"></i>
131 </a>
131 </a>
132 </div>
132 </div>
133 </div>
133 </div>
134 %endif
134 %endif
135 %if h.is_hg(c.db_repo_scm_instance):
135 %if h.is_hg(c.db_repo_scm_instance):
136 %for book in cs.bookmarks:
136 %for book in cs.bookmarks:
137 <div class="booktag" title="${_('Bookmark %s') % book}">
137 <div class="booktag" title="${_('Bookmark %s') % book}">
138 ${h.link_to(book,h.url('changeset_home',repo_name=c.repo_name,revision=cs.raw_id))}
138 ${h.link_to(book,h.url('changeset_home',repo_name=c.repo_name,revision=cs.raw_id))}
139 </div>
139 </div>
140 %endfor
140 %endfor
141 %endif
141 %endif
142 %for tag in cs.tags:
142 %for tag in cs.tags:
143 <div class="tagtag" title="${_('Tag %s') % tag}">
143 <div class="tagtag" title="${_('Tag %s') % tag}">
144 ${h.link_to(tag,h.url('changeset_home',repo_name=c.repo_name,revision=cs.raw_id))}
144 ${h.link_to(tag,h.url('changeset_home',repo_name=c.repo_name,revision=cs.raw_id))}
145 </div>
145 </div>
146 %endfor
146 %endfor
147 %if (not c.branch_name) and cs.branch:
147 %if (not c.branch_name) and cs.branch:
148 <div class="branchtag" title="${_('Branch %s' % cs.branch)}">
148 <div class="branchtag" title="${_('Branch %s' % cs.branch)}">
149 ${h.link_to(cs.branch,h.url('changelog_home',repo_name=c.repo_name,branch=cs.branch))}
149 ${h.link_to(cs.branch,h.url('changelog_home',repo_name=c.repo_name,branch=cs.branch))}
150 </div>
150 </div>
151 %endif
151 %endif
152 </div>
152 </div>
153 </div>
153 </div>
154 </td>
154 </td>
155 </tr>
155 </tr>
156 %endfor
156 %endfor
157 </tbody>
157 </tbody>
158 </table>
158 </table>
159
159
160 </div>
160 </div>
161
161
162 <div class="pagination-wh pagination-left">
162 <div class="pagination-wh pagination-left">
163 ${c.pagination.pager('$link_previous ~2~ $link_next')}
163 ${c.pagination.pager('$link_previous ~2~ $link_next')}
164 </div>
164 </div>
165 </div>
165 </div>
166 </div>
166 </div>
167
167
168 <script type="text/javascript" src="${h.url('/js/graph.js')}"></script>
168 <script type="text/javascript" src="${h.url('/js/graph.js')}"></script>
169 <script type="text/javascript">
169 <script type="text/javascript">
170 $(document).ready(function(){
170 $(document).ready(function(){
171 //Monitor range checkboxes and build a link to changesets ranges
171 //Monitor range checkboxes and build a link to changesets ranges
172 var checkboxes = YUD.getElementsByClassName('changeset_range');
172 var checkboxes = YUD.getElementsByClassName('changeset_range');
173 // register extra routes needed for this view
173 // register extra routes needed for this view
174 pyroutes.register('changeset_home', "${h.url('changeset_home', repo_name='%(repo_name)s', revision='%(revision)s')}", ['repo_name', 'revision']);
174 pyroutes.register('changeset_home', "${h.url('changeset_home', repo_name='%(repo_name)s', revision='%(revision)s')}", ['repo_name', 'revision']);
175
175
176 var checkbox_checker = function(e){
176 var checkbox_checker = function(e){
177 var checked_checkboxes = [];
177 var checked_checkboxes = [];
178 for (pos in checkboxes){
178 for (pos in checkboxes){
179 if(checkboxes[pos].checked){
179 if(checkboxes[pos].checked){
180 checked_checkboxes.push(checkboxes[pos]);
180 checked_checkboxes.push(checkboxes[pos]);
181 }
181 }
182 }
182 }
183 if(YUD.get('open_new_pr')){
183 if(YUD.get('open_new_pr')){
184 if(checked_checkboxes.length>1){
184 if(checked_checkboxes.length>1){
185 YUD.setStyle('open_new_pr','display','none');
185 YUD.setStyle('open_new_pr','display','none');
186 } else {
186 } else {
187 YUD.setStyle('open_new_pr','display','');
187 YUD.setStyle('open_new_pr','display','');
188 if(checked_checkboxes.length>0){
188 if(checked_checkboxes.length>0){
189 YUD.get('open_new_pr').innerHTML = _TM['Open new pull request for selected changesets'];
189 YUD.get('open_new_pr').innerHTML = _TM['Open new pull request for selected changesets'];
190 }else{
190 }else{
191 YUD.get('open_new_pr').innerHTML = _TM['Open new pull request'];
191 YUD.get('open_new_pr').innerHTML = _TM['Open new pull request'];
192 }
192 }
193 }
193 }
194 }
194 }
195
195
196 if(checked_checkboxes.length>0){
196 if(checked_checkboxes.length>0){
197 var rev_end = checked_checkboxes[0].name;
197 var rev_end = checked_checkboxes[0].name;
198 var rev_start = checked_checkboxes[checked_checkboxes.length-1].name;
198 var rev_start = checked_checkboxes[checked_checkboxes.length-1].name;
199 var url = pyroutes.url('changeset_home', {'repo_name': '${c.repo_name}',
199 var url = pyroutes.url('changeset_home', {'repo_name': '${c.repo_name}',
200 'revision': rev_start+'...'+rev_end});
200 'revision': rev_start+'...'+rev_end});
201
201
202 var link = (rev_start == rev_end)
202 var link = (rev_start == rev_end)
203 ? _TM['Show selected changeset __S']
203 ? _TM['Show selected changeset __S']
204 : _TM['Show selected changesets __S &rarr; __E'];
204 : _TM['Show selected changesets __S &rarr; __E'];
205
205
206 link = link.replace('__S',rev_start.substr(0,6));
206 link = link.replace('__S',rev_start.substr(0,6));
207 link = link.replace('__E',rev_end.substr(0,6));
207 link = link.replace('__E',rev_end.substr(0,6));
208 YUD.get('rev_range_container').href = url;
208 YUD.get('rev_range_container').href = url;
209 YUD.get('rev_range_container').innerHTML = link;
209 YUD.get('rev_range_container').innerHTML = link;
210 YUD.setStyle('rev_range_container','display','');
210 YUD.setStyle('rev_range_container','display','');
211 YUD.setStyle('rev_range_clear','display','');
211 YUD.setStyle('rev_range_clear','display','');
212
212
213 YUD.get('open_new_pr').href = pyroutes.url('pullrequest_home',
213 YUD.get('open_new_pr').href = pyroutes.url('pullrequest_home',
214 {'repo_name': '${c.repo_name}',
214 {'repo_name': '${c.repo_name}',
215 'rev_start': rev_start,
215 'rev_start': rev_start,
216 'rev_end': rev_end})
216 'rev_end': rev_end})
217
217
218 YUD.setStyle('compare_fork','display','none');
218 YUD.setStyle('compare_fork','display','none');
219 }else{
219 }else{
220 YUD.setStyle('rev_range_container','display','none');
220 YUD.setStyle('rev_range_container','display','none');
221 YUD.setStyle('rev_range_clear','display','none');
221 YUD.setStyle('rev_range_clear','display','none');
222 %if c.revision:
222 %if c.revision:
223 YUD.get('open_new_pr').href = pyroutes.url('pullrequest_home',
223 YUD.get('open_new_pr').href = pyroutes.url('pullrequest_home',
224 {'repo_name': '${c.repo_name}',
224 {'repo_name': '${c.repo_name}',
225 'rev_end':'${c.first_revision.raw_id}'});
225 'rev_end':'${c.first_revision.raw_id}'});
226 %else:
226 %else:
227 YUD.get('open_new_pr').href = pyroutes.url('pullrequest_home',
227 YUD.get('open_new_pr').href = pyroutes.url('pullrequest_home',
228 {'repo_name': '${c.repo_name}',
228 {'repo_name': '${c.repo_name}',
229 'branch':'${c.first_revision.branch}'});
229 'branch':'${c.first_revision.branch}'});
230 %endif
230 %endif
231 YUD.setStyle('compare_fork','display','');
231 YUD.setStyle('compare_fork','display','');
232 }
232 }
233 };
233 };
234 checkbox_checker();
234 checkbox_checker();
235 YUE.on(checkboxes,'click', checkbox_checker);
235 YUE.on(checkboxes,'click', checkbox_checker);
236
236
237 YUE.on('rev_range_clear','click',function(e){
237 YUE.on('rev_range_clear','click',function(e){
238 for (var i=0; i<checkboxes.length; i++){
238 for (var i=0; i<checkboxes.length; i++){
239 var cb = checkboxes[i];
239 var cb = checkboxes[i];
240 cb.checked = false;
240 cb.checked = false;
241 }
241 }
242 checkbox_checker();
242 checkbox_checker();
243 YUE.preventDefault(e);
243 YUE.preventDefault(e);
244 });
244 });
245
245
246 var msgs = YUQ('.message');
246 var msgs = YUQ('.message');
247 // get first element height
247 // get first element height
248 var el = YUQ('#graph_content .container')[0];
248 var el = YUQ('#graph_content .container')[0];
249 var row_h = el.clientHeight;
249 var row_h = el.clientHeight;
250 for(var i=0;i<msgs.length;i++){
250 for(var i=0;i<msgs.length;i++){
251 var m = msgs[i];
251 var m = msgs[i];
252
252
253 var h = m.clientHeight;
253 var h = m.clientHeight;
254 var pad = YUD.getStyle(m,'padding');
254 var pad = YUD.getStyle(m,'padding');
255 if(h > row_h){
255 if(h > row_h){
256 var offset = row_h - (h+12);
256 var offset = row_h - (h+12);
257 YUD.setStyle(m.nextElementSibling,'display','block');
257 YUD.setStyle(m.nextElementSibling,'display','block');
258 YUD.setStyle(m.nextElementSibling,'margin-top',offset+'px');
258 YUD.setStyle(m.nextElementSibling,'margin-top',offset+'px');
259 };
259 };
260 }
260 }
261
261
262 $('.expand_commit').on('click',function(e){
262 $('.expand_commit').on('click',function(e){
263 var cid = $(this).attr('commit_id');
263 var cid = $(this).attr('commit_id');
264 $('#C-'+cid).toggleClass('expanded');
264 $('#C-'+cid).toggleClass('expanded');
265
265
266 //redraw the graph, r and jsdata are bound outside function
266 //redraw the graph, r and jsdata are bound outside function
267 r.render(jsdata,100);
267 r.render(jsdata,100);
268 });
268 });
269
269
270 // change branch filter
270 // change branch filter
271 $("#branch_filter").select2({
271 $("#branch_filter").select2({
272 dropdownAutoWidth: true,
272 dropdownAutoWidth: true,
273 minimumInputLength: 1,
273 minimumInputLength: 1
274 });
274 });
275
275
276 $("#branch_filter").change(function(e){
276 $("#branch_filter").change(function(e){
277 var selected_branch = e.currentTarget.options[e.currentTarget.selectedIndex].value;
277 var selected_branch = e.currentTarget.options[e.currentTarget.selectedIndex].value;
278 if(selected_branch != ''){
278 if(selected_branch != ''){
279 window.location = pyroutes.url('changelog_home', {'repo_name': '${c.repo_name}',
279 window.location = pyroutes.url('changelog_home', {'repo_name': '${c.repo_name}',
280 'branch': selected_branch});
280 'branch': selected_branch});
281 }else{
281 }else{
282 window.location = pyroutes.url('changelog_home', {'repo_name': '${c.repo_name}'});
282 window.location = pyroutes.url('changelog_home', {'repo_name': '${c.repo_name}'});
283 }
283 }
284 $("#changelog").hide();
284 $("#changelog").hide();
285 });
285 });
286
286
287 var jsdata = ${c.jsdata|n};
287 var jsdata = ${c.jsdata|n};
288 var r = new BranchRenderer('graph_canvas', 'graph_content');
288 var r = new BranchRenderer('graph_canvas', 'graph_content');
289 r.render(jsdata,100);
289 r.render(jsdata,100);
290 });
290 });
291
291
292 </script>
292 </script>
293 %else:
293 %else:
294 ${_('There are no changes yet')}
294 ${_('There are no changes yet')}
295 %endif
295 %endif
296 </div>
296 </div>
297 </div>
297 </div>
298 </%def>
298 </%def>
@@ -1,292 +1,291 b''
1 ## -*- coding: utf-8 -*-
1 ## -*- coding: utf-8 -*-
2
2
3 <%inherit file="/base/base.html"/>
3 <%inherit file="/base/base.html"/>
4
4
5 <%def name="title()">
5 <%def name="title()">
6 ${_('%s Changeset') % c.repo_name} - ${h.show_id(c.changeset)}
6 ${_('%s Changeset') % c.repo_name} - ${h.show_id(c.changeset)}
7 %if c.site_name:
7 %if c.site_name:
8 &middot; ${c.site_name}
8 &middot; ${c.site_name}
9 %endif
9 %endif
10 </%def>
10 </%def>
11
11
12 <%def name="breadcrumbs_links()">
12 <%def name="breadcrumbs_links()">
13 ${_('Changeset')} - <span class='hash'>${h.show_id(c.changeset)}</span>
13 ${_('Changeset')} - <span class='hash'>${h.show_id(c.changeset)}</span>
14 </%def>
14 </%def>
15
15
16 <%def name="page_nav()">
16 <%def name="page_nav()">
17 ${self.menu('repositories')}
17 ${self.menu('repositories')}
18 </%def>
18 </%def>
19
19
20 <%def name="main()">
20 <%def name="main()">
21 ${self.repo_context_bar('changelog', c.changeset.raw_id)}
21 ${self.repo_context_bar('changelog', c.changeset.raw_id)}
22 <div class="box">
22 <div class="box">
23 <!-- box / title -->
23 <!-- box / title -->
24 <div class="title">
24 <div class="title">
25 ${self.breadcrumbs()}
25 ${self.breadcrumbs()}
26 </div>
26 </div>
27 <script>
27 <script>
28 var _USERS_AC_DATA = ${c.users_array|n};
28 var _USERS_AC_DATA = ${c.users_array|n};
29 var _GROUPS_AC_DATA = ${c.user_groups_array|n};
29 var _GROUPS_AC_DATA = ${c.user_groups_array|n};
30 AJAX_COMMENT_URL = "${url('changeset_comment',repo_name=c.repo_name,revision=c.changeset.raw_id)}";
30 AJAX_COMMENT_URL = "${url('changeset_comment',repo_name=c.repo_name,revision=c.changeset.raw_id)}";
31 AJAX_COMMENT_DELETE_URL = "${url('changeset_comment_delete',repo_name=c.repo_name,comment_id='__COMMENT_ID__')}";
31 AJAX_COMMENT_DELETE_URL = "${url('changeset_comment_delete',repo_name=c.repo_name,comment_id='__COMMENT_ID__')}";
32 </script>
32 </script>
33 <div class="table">
33 <div class="table">
34 <div class="diffblock">
34 <div class="diffblock">
35 <div class="parents">
35 <div class="parents">
36 <div id="parent_link" class="changeset_hash">
36 <div id="parent_link" class="changeset_hash">
37 <i style="color:#036185" class="icon-chevron-left"></i> <a href="#">${_('parent rev.')}</a>
37 <i style="color:#036185" class="icon-chevron-left"></i> <a href="#">${_('parent rev.')}</a>
38 </div>
38 </div>
39 </div>
39 </div>
40
40
41 <div class="children">
41 <div class="children">
42 <div id="child_link" class="changeset_hash">
42 <div id="child_link" class="changeset_hash">
43 <a href="#">${_('child rev.')}</a> <i style="color:#036185" class="icon-chevron-right"></i>
43 <a href="#">${_('child rev.')}</a> <i style="color:#036185" class="icon-chevron-right"></i>
44 </div>
44 </div>
45 </div>
45 </div>
46
46
47 <div class="code-header banner">
47 <div class="code-header banner">
48 <div class="changeset-status-container">
48 <div class="changeset-status-container">
49 %if c.statuses:
49 %if c.statuses:
50 <div class="changeset-status-ico"><img src="${h.url('/images/icons/flag_status_%s.png' % c.statuses[0])}" /></div>
50 <div class="changeset-status-ico"><img src="${h.url('/images/icons/flag_status_%s.png' % c.statuses[0])}" /></div>
51 <div title="${_('Changeset status')}" class="changeset-status-lbl">[${h.changeset_status_lbl(c.statuses[0])}]</div>
51 <div title="${_('Changeset status')}" class="changeset-status-lbl">[${h.changeset_status_lbl(c.statuses[0])}]</div>
52 %endif
52 %endif
53 </div>
53 </div>
54 <div class="diff-actions">
54 <div class="diff-actions">
55 <a href="${h.url('changeset_raw_home',repo_name=c.repo_name,revision=c.changeset.raw_id)}" class="tooltip" title="${h.tooltip(_('Raw diff'))}">
55 <a href="${h.url('changeset_raw_home',repo_name=c.repo_name,revision=c.changeset.raw_id)}" class="tooltip" title="${h.tooltip(_('Raw diff'))}">
56 <img class="icon" src="${h.url('/images/icons/page_white.png')}"/>
56 <img class="icon" src="${h.url('/images/icons/page_white.png')}"/>
57 </a>
57 </a>
58 <a href="${h.url('changeset_patch_home',repo_name=c.repo_name,revision=c.changeset.raw_id)}" class="tooltip" title="${h.tooltip(_('Patch diff'))}">
58 <a href="${h.url('changeset_patch_home',repo_name=c.repo_name,revision=c.changeset.raw_id)}" class="tooltip" title="${h.tooltip(_('Patch diff'))}">
59 <img class="icon" src="${h.url('/images/icons/page_add.png')}"/>
59 <img class="icon" src="${h.url('/images/icons/page_add.png')}"/>
60 </a>
60 </a>
61 <a href="${h.url('changeset_download_home',repo_name=c.repo_name,revision=c.changeset.raw_id,diff='download')}" class="tooltip" title="${h.tooltip(_('Download diff'))}">
61 <a href="${h.url('changeset_download_home',repo_name=c.repo_name,revision=c.changeset.raw_id,diff='download')}" class="tooltip" title="${h.tooltip(_('Download diff'))}">
62 <img class="icon" src="${h.url('/images/icons/page_save.png')}"/>
62 <img class="icon" src="${h.url('/images/icons/page_save.png')}"/>
63 </a>
63 </a>
64 ${c.ignorews_url(request.GET)}
64 ${c.ignorews_url(request.GET)}
65 ${c.context_url(request.GET)}
65 ${c.context_url(request.GET)}
66 </div>
66 </div>
67 <div class="comments-number" style="float:right;padding-right:5px">${ungettext("%d comment", "%d comments", len(c.comments)) % len(c.comments)} ${ungettext("(%d inline)", "(%d inline)", c.inline_cnt) % c.inline_cnt} <span class="firstlink"></span> </div>
67 <div class="comments-number" style="float:right;padding-right:5px">${ungettext("%d comment", "%d comments", len(c.comments)) % len(c.comments)} ${ungettext("(%d inline)", "(%d inline)", c.inline_cnt) % c.inline_cnt} <span class="firstlink"></span> </div>
68 </div>
68 </div>
69 </div>
69 </div>
70 <div id="changeset_content">
70 <div id="changeset_content">
71 <div class="container">
71 <div class="container">
72
72
73 <div class="right">
73 <div class="right">
74 <div class="changes">
74 <div class="changes">
75 % if (len(c.changeset.affected_files) <= c.affected_files_cut_off) or c.fulldiff:
75 % if (len(c.changeset.affected_files) <= c.affected_files_cut_off) or c.fulldiff:
76 <span class="removed" title="${_('Removed')}">${len(c.changeset.removed)}</span>
76 <span class="removed" title="${_('Removed')}">${len(c.changeset.removed)}</span>
77 <span class="changed" title="${_('Changed')}">${len(c.changeset.changed)}</span>
77 <span class="changed" title="${_('Changed')}">${len(c.changeset.changed)}</span>
78 <span class="added" title="${_('Added')}">${len(c.changeset.added)}</span>
78 <span class="added" title="${_('Added')}">${len(c.changeset.added)}</span>
79 % else:
79 % else:
80 <span class="removed" title="${_('Affected %s files') % len(c.changeset.affected_files)}">!</span>
80 <span class="removed" title="${_('Affected %s files') % len(c.changeset.affected_files)}">!</span>
81 <span class="changed" title="${_('Affected %s files') % len(c.changeset.affected_files)}">!</span>
81 <span class="changed" title="${_('Affected %s files') % len(c.changeset.affected_files)}">!</span>
82 <span class="added" title="${_('Affected %s files') % len(c.changeset.affected_files)}">!</span>
82 <span class="added" title="${_('Affected %s files') % len(c.changeset.affected_files)}">!</span>
83 % endif
83 % endif
84 </div>
84 </div>
85
85
86 <span class="logtags">
86 <span class="logtags">
87 %if len(c.changeset.parents)>1:
87 %if len(c.changeset.parents)>1:
88 <span class="merge">${_('merge')}</span>
88 <span class="merge">${_('merge')}</span>
89 %endif
89 %endif
90
90
91 %if h.is_hg(c.db_repo_scm_instance):
91 %if h.is_hg(c.db_repo_scm_instance):
92 %for book in c.changeset.bookmarks:
92 %for book in c.changeset.bookmarks:
93 <span class="booktag" title="${_('Bookmark %s') % book}">
93 <span class="booktag" title="${_('Bookmark %s') % book}">
94 ${h.link_to(book,h.url('changeset_home',repo_name=c.repo_name,revision=c.changeset.raw_id))}
94 ${h.link_to(book,h.url('changeset_home',repo_name=c.repo_name,revision=c.changeset.raw_id))}
95 </span>
95 </span>
96 %endfor
96 %endfor
97 %endif
97 %endif
98
98
99 %for tag in c.changeset.tags:
99 %for tag in c.changeset.tags:
100 <span class="tagtag" title="${_('Tag %s') % tag}">
100 <span class="tagtag" title="${_('Tag %s') % tag}">
101 ${h.link_to(tag,h.url('changeset_home',repo_name=c.repo_name,revision=c.changeset.raw_id))}</span>
101 ${h.link_to(tag,h.url('changeset_home',repo_name=c.repo_name,revision=c.changeset.raw_id))}</span>
102 %endfor
102 %endfor
103
103
104 %if c.changeset.branch:
104 %if c.changeset.branch:
105 <span class="branchtag" title="${_('Branch %s') % c.changeset.branch}">
105 <span class="branchtag" title="${_('Branch %s') % c.changeset.branch}">
106 ${h.link_to(c.changeset.branch,h.url('changelog_home',repo_name=c.repo_name,branch=c.changeset.branch))}
106 ${h.link_to(c.changeset.branch,h.url('changelog_home',repo_name=c.repo_name,branch=c.changeset.branch))}
107 </span>
107 </span>
108 %endif
108 %endif
109 </span>
109 </span>
110 </div>
110 </div>
111 <div class="left">
111 <div class="left">
112 <div class="author">
112 <div class="author">
113 <div class="gravatar">
113 <div class="gravatar">
114 <img alt="gravatar" src="${h.gravatar_url(h.email_or_none(c.changeset.author),20)}"/>
114 <img alt="gravatar" src="${h.gravatar_url(h.email_or_none(c.changeset.author),20)}"/>
115 </div>
115 </div>
116 <span><b>${h.person(c.changeset.author,'username_and_name')}</b> - ${h.age(c.changeset.date,True)} ${h.fmt_date(c.changeset.date)}</span><br/>
116 <span><b>${h.person(c.changeset.author,'username_and_name')}</b> - ${h.age(c.changeset.date,True)} ${h.fmt_date(c.changeset.date)}</span><br/>
117 <span>${h.email_or_none(c.changeset.author)}</span><br/>
117 <span>${h.email_or_none(c.changeset.author)}</span><br/>
118 </div>
118 </div>
119 <% rev = c.changeset.extra.get('source') %>
119 <% rev = c.changeset.extra.get('source') %>
120 %if rev:
120 %if rev:
121 <div>
121 <div>
122 ${_('Grafted from:')} ${h.link_to(h.short_id(rev),h.url('changeset_home',repo_name=c.repo_name,revision=rev))}
122 ${_('Grafted from:')} ${h.link_to(h.short_id(rev),h.url('changeset_home',repo_name=c.repo_name,revision=rev))}
123 </div>
123 </div>
124 %endif
124 %endif
125 <% rev = c.changeset.extra.get('transplant_source', '').encode('hex') %>
125 <% rev = c.changeset.extra.get('transplant_source', '').encode('hex') %>
126 %if rev:
126 %if rev:
127 <div>
127 <div>
128 ${_('Transplanted from:')} ${h.link_to(h.short_id(rev),h.url('changeset_home',repo_name=c.repo_name,revision=rev))}
128 ${_('Transplanted from:')} ${h.link_to(h.short_id(rev),h.url('changeset_home',repo_name=c.repo_name,revision=rev))}
129 </div>
129 </div>
130 %endif
130 %endif
131 <div class="message">${h.urlify_commit(c.changeset.message, c.repo_name)}</div>
131 <div class="message">${h.urlify_commit(c.changeset.message, c.repo_name)}</div>
132 </div>
132 </div>
133 </div>
133 </div>
134 <div class="changes_txt">
134 <div class="changes_txt">
135 % if c.limited_diff:
135 % if c.limited_diff:
136 ${ungettext('%s file changed','%s files changed',len(c.changeset.affected_files)) % (len(c.changeset.affected_files))}:
136 ${ungettext('%s file changed','%s files changed',len(c.changeset.affected_files)) % (len(c.changeset.affected_files))}:
137 % else:
137 % else:
138 ${ungettext('%s file changed with %s insertions and %s deletions','%s files changed with %s insertions and %s deletions', len(c.changeset.affected_files)) % (len(c.changeset.affected_files),c.lines_added,c.lines_deleted)}:
138 ${ungettext('%s file changed with %s insertions and %s deletions','%s files changed with %s insertions and %s deletions', len(c.changeset.affected_files)) % (len(c.changeset.affected_files),c.lines_added,c.lines_deleted)}:
139 %endif
139 %endif
140 </div>
140 </div>
141 <div class="cs_files">
141 <div class="cs_files">
142 %for FID, (cs1, cs2, change, path, diff, stats) in c.changes[c.changeset.raw_id].iteritems():
142 %for FID, (cs1, cs2, change, path, diff, stats) in c.changes[c.changeset.raw_id].iteritems():
143 <div class="cs_${change}">
143 <div class="cs_${change}">
144 <div class="node">
144 <div class="node">
145 <a href="#${FID}">${h.safe_unicode(path)}</a>
145 <a href="#${FID}">${h.safe_unicode(path)}</a>
146 </div>
146 </div>
147 <div class="changes">${h.fancy_file_stats(stats)}</div>
147 <div class="changes">${h.fancy_file_stats(stats)}</div>
148 </div>
148 </div>
149 %endfor
149 %endfor
150 % if c.limited_diff:
150 % if c.limited_diff:
151 <h5>${_('Changeset was too big and was cut off...')} <a href="${h.url.current(fulldiff=1, **request.GET.mixed())}">${_('Show full diff anyway')}</a></h5>
151 <h5>${_('Changeset was too big and was cut off...')} <a href="${h.url.current(fulldiff=1, **request.GET.mixed())}">${_('Show full diff anyway')}</a></h5>
152 % endif
152 % endif
153 </div>
153 </div>
154 </div>
154 </div>
155
155
156 </div>
156 </div>
157
157
158 ## diff block
158 ## diff block
159 <%namespace name="diff_block" file="/changeset/diff_block.html"/>
159 <%namespace name="diff_block" file="/changeset/diff_block.html"/>
160 ${diff_block.diff_block_js()}
160 ${diff_block.diff_block_js()}
161 ${diff_block.diff_block(c.changes[c.changeset.raw_id])}
161 ${diff_block.diff_block(c.changes[c.changeset.raw_id])}
162
162
163 % if c.limited_diff:
163 % if c.limited_diff:
164 <h4>${_('Changeset was too big and was cut off...')} <a href="${h.url.current(fulldiff=1, **request.GET.mixed())}">${_('Show full diff anyway')}</a></h4>
164 <h4>${_('Changeset was too big and was cut off...')} <a href="${h.url.current(fulldiff=1, **request.GET.mixed())}">${_('Show full diff anyway')}</a></h4>
165 % endif
165 % endif
166
166
167 ## template for inline comment form
167 ## template for inline comment form
168 <%namespace name="comment" file="/changeset/changeset_file_comment.html"/>
168 <%namespace name="comment" file="/changeset/changeset_file_comment.html"/>
169 ${comment.comment_inline_form()}
169 ${comment.comment_inline_form()}
170
170
171 ## render comments and inlines
171 ## render comments and inlines
172 ${comment.generate_comments()}
172 ${comment.generate_comments()}
173
173
174 ## main comment form and it status
174 ## main comment form and it status
175 ${comment.comments(h.url('changeset_comment', repo_name=c.repo_name, revision=c.changeset.raw_id),
175 ${comment.comments(h.url('changeset_comment', repo_name=c.repo_name, revision=c.changeset.raw_id),
176 h.changeset_status(c.db_repo, c.changeset.raw_id))}
176 h.changeset_status(c.db_repo, c.changeset.raw_id))}
177
177
178 ## FORM FOR MAKING JS ACTION AS CHANGESET COMMENTS
178 ## FORM FOR MAKING JS ACTION AS CHANGESET COMMENTS
179 <script type="text/javascript">
179 <script type="text/javascript">
180 $(document).ready(function(){
180 $(document).ready(function(){
181 $('.show-inline-comments').change(function(e){
181 $('.show-inline-comments').change(function(e){
182 var target = e.currentTarget;
182 var target = e.currentTarget;
183 if(target == null){
183 if(target == null){
184 target = this;
184 target = this;
185 }
185 }
186 var boxid = $(target).attr('id_for');
186 var boxid = $(target).attr('id_for');
187 if(target.checked){
187 if(target.checked){
188 $('#{0} .inline-comments'.format(boxid)).show();
188 $('#{0} .inline-comments'.format(boxid)).show();
189 $('#{0} .inline-comments-button'.format(boxid)).show();
189 $('#{0} .inline-comments-button'.format(boxid)).show();
190 }else{
190 }else{
191 $('#{0} .inline-comments'.format(boxid)).hide();
191 $('#{0} .inline-comments'.format(boxid)).hide();
192 $('#{0} .inline-comments-button'.format(boxid)).hide();
192 $('#{0} .inline-comments-button'.format(boxid)).hide();
193 }
193 }
194 });
194 });
195 $('.add-bubble').click(function(e){
195 $('.add-bubble').click(function(e){
196 var tr = e.currentTarget;
196 var tr = e.currentTarget;
197 if(tr == null){
197 if(tr == null){
198 tr = this;
198 tr = this;
199 }
199 }
200 injectInlineForm(tr.parentNode.parentNode);
200 injectInlineForm(tr.parentNode.parentNode);
201 });
201 });
202
202
203 // inject comments into they proper positions
203 // inject comments into they proper positions
204 var file_comments = YUQ('.inline-comment-placeholder');
204 var file_comments = YUQ('.inline-comment-placeholder');
205 renderInlineComments(file_comments);
205 renderInlineComments(file_comments);
206
206
207 linkInlineComments(document.getElementsByClassName('firstlink'), document.getElementsByClassName("inline-comment"));
207 linkInlineComments(document.getElementsByClassName('firstlink'), document.getElementsByClassName("inline-comment"));
208
208
209 pyroutes.register('changeset_home',
209 pyroutes.register('changeset_home',
210 "${h.url('changeset_home', repo_name='%(repo_name)s', revision='%(revision)s')}",
210 "${h.url('changeset_home', repo_name='%(repo_name)s', revision='%(revision)s')}",
211 ['repo_name', 'revision']);
211 ['repo_name', 'revision']);
212
212
213 //next links
213 //next links
214 $('#child_link').on('click', function(e){
214 $('#child_link').on('click', function(e){
215 //fetch via ajax what is going to be the next link, if we have
215 //fetch via ajax what is going to be the next link, if we have
216 //>1 links show them to user to choose
216 //>1 links show them to user to choose
217 if(!$('#child_link').hasClass('disabled')){
217 if(!$('#child_link').hasClass('disabled')){
218 $.ajax({
218 $.ajax({
219 url: '${h.url('changeset_children',repo_name=c.repo_name, revision=c.changeset.raw_id)}',
219 url: '${h.url('changeset_children',repo_name=c.repo_name, revision=c.changeset.raw_id)}',
220 success: function(data) {
220 success: function(data) {
221 if(data.results.length === 0){
221 if(data.results.length === 0){
222 $('#child_link').addClass('disabled');
222 $('#child_link').addClass('disabled');
223 $('#child_link').html('${_('no revisions')}');
223 $('#child_link').html('${_('no revisions')}');
224 }
224 }
225 if(data.results.length === 1){
225 if(data.results.length === 1){
226 var commit = data.results[0];
226 var commit = data.results[0];
227 window.location = pyroutes.url('changeset_home', {'repo_name': '${c.repo_name}','revision': commit.raw_id});
227 window.location = pyroutes.url('changeset_home', {'repo_name': '${c.repo_name}','revision': commit.raw_id});
228 }
228 }
229 else if(data.results.length === 2){
229 else if(data.results.length === 2){
230 $('#child_link').addClass('disabled');
230 $('#child_link').addClass('disabled');
231 $('#child_link').addClass('double');
231 $('#child_link').addClass('double');
232 var _html = '';
232 var _html = '';
233 _html +='<a title="__title__" href="__url__">__rev__</a> <i style="color:#036185" class="icon-chevron-right"></i>'
233 _html +='<a title="__title__" href="__url__">__rev__</a> <i style="color:#036185" class="icon-chevron-right"></i>'
234 .replace('__rev__','r{0}:{1}'.format(data.results[0].revision, data.results[0].raw_id.substr(0,6)))
234 .replace('__rev__','r{0}:{1}'.format(data.results[0].revision, data.results[0].raw_id.substr(0,6)))
235 .replace('__title__', data.results[0].message)
235 .replace('__title__', data.results[0].message)
236 .replace('__url__', pyroutes.url('changeset_home', {'repo_name': '${c.repo_name}','revision': data.results[0].raw_id}));
236 .replace('__url__', pyroutes.url('changeset_home', {'repo_name': '${c.repo_name}','revision': data.results[0].raw_id}));
237 _html +='<br/>'
237 _html +='<br/>'
238 _html +='<a title="__title__" href="__url__">__rev__</a> <i style="color:#036185" class="icon-chevron-right"></i>'
238 _html +='<a title="__title__" href="__url__">__rev__</a> <i style="color:#036185" class="icon-chevron-right"></i>'
239 .replace('__rev__','r{0}:{1}'.format(data.results[1].revision, data.results[1].raw_id.substr(0,6)))
239 .replace('__rev__','r{0}:{1}'.format(data.results[1].revision, data.results[1].raw_id.substr(0,6)))
240 .replace('__title__', data.results[1].message)
240 .replace('__title__', data.results[1].message)
241 .replace('__url__', pyroutes.url('changeset_home', {'repo_name': '${c.repo_name}','revision': data.results[1].raw_id}));
241 .replace('__url__', pyroutes.url('changeset_home', {'repo_name': '${c.repo_name}','revision': data.results[1].raw_id}));
242 $('#child_link').html(_html);
242 $('#child_link').html(_html);
243 }
243 }
244 },
244 }
245 });
245 });
246 e.preventDefault();
246 e.preventDefault();
247 }
247 }
248 })
248 })
249
249
250 //prev links
250 //prev links
251 $('#parent_link').on('click', function(e){
251 $('#parent_link').on('click', function(e){
252 //fetch via ajax what is going to be the next link, if we have
252 //fetch via ajax what is going to be the next link, if we have
253 //>1 links show them to user to choose
253 //>1 links show them to user to choose
254 if(!$('#parent_link').hasClass('disabled')){
254 if(!$('#parent_link').hasClass('disabled')){
255 $.ajax({
255 $.ajax({
256 url: '${h.url('changeset_parents',repo_name=c.repo_name, revision=c.changeset.raw_id)}',
256 url: '${h.url('changeset_parents',repo_name=c.repo_name, revision=c.changeset.raw_id)}',
257 success: function(data) {
257 success: function(data) {
258 if(data.results.length === 0){
258 if(data.results.length === 0){
259 $('#parent_link').addClass('disabled');
259 $('#parent_link').addClass('disabled');
260 $('#parent_link').html('${_('no revisions')}');
260 $('#parent_link').html('${_('no revisions')}');
261 }
261 }
262 if(data.results.length === 1){
262 if(data.results.length === 1){
263 var commit = data.results[0];
263 var commit = data.results[0];
264 window.location = pyroutes.url('changeset_home', {'repo_name': '${c.repo_name}','revision': commit.raw_id});
264 window.location = pyroutes.url('changeset_home', {'repo_name': '${c.repo_name}','revision': commit.raw_id});
265 }
265 }
266 else if(data.results.length === 2){
266 else if(data.results.length === 2){
267 $('#parent_link').addClass('disabled');
267 $('#parent_link').addClass('disabled');
268 $('#parent_link').addClass('double');
268 $('#parent_link').addClass('double');
269 var _html = '';
269 var _html = '';
270 _html +='<i style="color:#036185" class="icon-chevron-left"></i> <a title="__title__" href="__url__">__rev__</a>'
270 _html +='<i style="color:#036185" class="icon-chevron-left"></i> <a title="__title__" href="__url__">__rev__</a>'
271 .replace('__rev__','r{0}:{1}'.format(data.results[0].revision, data.results[0].raw_id.substr(0,6)))
271 .replace('__rev__','r{0}:{1}'.format(data.results[0].revision, data.results[0].raw_id.substr(0,6)))
272 .replace('__title__', data.results[0].message)
272 .replace('__title__', data.results[0].message)
273 .replace('__url__', pyroutes.url('changeset_home', {'repo_name': '${c.repo_name}','revision': data.results[0].raw_id}));
273 .replace('__url__', pyroutes.url('changeset_home', {'repo_name': '${c.repo_name}','revision': data.results[0].raw_id}));
274 _html +='<br/>'
274 _html +='<br/>'
275 _html +='<i style="color:#036185" class="icon-chevron-left"></i> <a title="__title__" href="__url__">__rev__</a>'
275 _html +='<i style="color:#036185" class="icon-chevron-left"></i> <a title="__title__" href="__url__">__rev__</a>'
276 .replace('__rev__','r{0}:{1}'.format(data.results[1].revision, data.results[1].raw_id.substr(0,6)))
276 .replace('__rev__','r{0}:{1}'.format(data.results[1].revision, data.results[1].raw_id.substr(0,6)))
277 .replace('__title__', data.results[1].message)
277 .replace('__title__', data.results[1].message)
278 .replace('__url__', pyroutes.url('changeset_home', {'repo_name': '${c.repo_name}','revision': data.results[1].raw_id}));
278 .replace('__url__', pyroutes.url('changeset_home', {'repo_name': '${c.repo_name}','revision': data.results[1].raw_id}));
279 $('#parent_link').html(_html);
279 $('#parent_link').html(_html);
280 }
280 }
281 },
281 }
282 });
282 });
283 e.preventDefault();
283 e.preventDefault();
284 }
284 }
285 })
285 })
286
287 })
286 })
288
287
289 </script>
288 </script>
290
289
291 </div>
290 </div>
292 </%def>
291 </%def>
@@ -1,119 +1,119 b''
1 ## Changesets table !
1 ## Changesets table !
2 <div class="container">
2 <div class="container">
3 %if not c.cs_ranges:
3 %if not c.cs_ranges:
4 <span class="empty_data">${_('No changesets')}</span>
4 <span class="empty_data">${_('No changesets')}</span>
5 %else:
5 %else:
6
6
7 %if c.ancestor:
7 %if c.ancestor:
8 <div class="ancestor">${_('Ancestor')}:
8 <div class="ancestor">${_('Ancestor')}:
9 ${h.link_to(h.short_id(c.ancestor),h.url('changeset_home',repo_name=c.repo_name,revision=c.ancestor))}
9 ${h.link_to(h.short_id(c.ancestor),h.url('changeset_home',repo_name=c.repo_name,revision=c.ancestor))}
10 </div>
10 </div>
11 %endif
11 %endif
12
12
13 <div id="graph_nodes">
13 <div id="graph_nodes">
14 <canvas id="graph_canvas"></canvas>
14 <canvas id="graph_canvas"></canvas>
15 </div>
15 </div>
16
16
17 <div id="graph_content_pr" style="margin-left: 100px;">
17 <div id="graph_content_pr" style="margin-left: 100px;">
18
18
19 <table class="compare_view_commits noborder">
19 <table class="compare_view_commits noborder">
20 %for cnt, cs in enumerate(reversed(c.cs_ranges)):
20 %for cnt, cs in enumerate(reversed(c.cs_ranges)):
21 <tr id="chg_${cnt+1}">
21 <tr id="chg_${cnt+1}">
22 <td style="width:50px">
22 <td style="width:50px">
23 %if cs.raw_id in c.statuses:
23 %if cs.raw_id in c.statuses:
24 <div title="${_('Changeset status: %s') % c.statuses[cs.raw_id][1]}" class="changeset-status-ico">
24 <div title="${_('Changeset status: %s') % c.statuses[cs.raw_id][1]}" class="changeset-status-ico">
25 <img height="16" width="16" src="${h.url('/images/icons/flag_status_%s.png' % c.statuses[cs.raw_id][0])}" />
25 <img height="16" width="16" src="${h.url('/images/icons/flag_status_%s.png' % c.statuses[cs.raw_id][0])}" />
26 </div>
26 </div>
27 %endif
27 %endif
28 %if c.cs_comments.get(cs.raw_id):
28 %if c.cs_comments.get(cs.raw_id):
29 <div class="comments-container">
29 <div class="comments-container">
30 <div class="comments-cnt" title="${_('Changeset has comments')}">
30 <div class="comments-cnt" title="${_('Changeset has comments')}">
31 <a href="${h.url('changeset_home',repo_name=c.cs_repo.repo_name,revision=cs.raw_id,anchor='comment-%s' % c.cs_comments[cs.raw_id][0].comment_id)}">
31 <a href="${h.url('changeset_home',repo_name=c.cs_repo.repo_name,revision=cs.raw_id,anchor='comment-%s' % c.cs_comments[cs.raw_id][0].comment_id)}">
32 ${len(c.cs_comments[cs.raw_id])}
32 ${len(c.cs_comments[cs.raw_id])}
33 <i class="icon-comment-alt icon-comment-colored"></i>
33 <i class="icon-comment-alt icon-comment-colored"></i>
34 </a>
34 </a>
35 </div>
35 </div>
36 </div>
36 </div>
37 %endif
37 %endif
38 </td>
38 </td>
39 <td style="width: 140px"><span class="tooltip" title="${h.tooltip(h.age(cs.date))}">${cs.date}</span></td>
39 <td style="width: 140px"><span class="tooltip" title="${h.tooltip(h.age(cs.date))}">${cs.date}</span></td>
40 <td><div class="gravatar" commit_id="${cs.raw_id}"><img alt="gravatar" src="${h.gravatar_url(h.email_or_none(cs.author),14)}" height="14" width="14"/></div></td>
40 <td><div class="gravatar" commit_id="${cs.raw_id}"><img alt="gravatar" src="${h.gravatar_url(h.email_or_none(cs.author),14)}" height="14" width="14"/></div></td>
41 <td><div class="author">${h.person(cs.author)}</div></td>
41 <td><div class="author">${h.person(cs.author)}</div></td>
42 <td>${h.link_to(h.show_id(cs),h.url('changeset_home',repo_name=c.cs_repo.repo_name,revision=cs.raw_id))}</td>
42 <td>${h.link_to(h.show_id(cs),h.url('changeset_home',repo_name=c.cs_repo.repo_name,revision=cs.raw_id))}</td>
43 <td>
43 <td>
44 %if cs.branch:
44 %if cs.branch:
45 <span class="branchtag">${h.link_to(cs.branch,h.url('changelog_home',repo_name=c.cs_repo.repo_name,branch=cs.branch))}</span>
45 <span class="branchtag">${h.link_to(cs.branch,h.url('changelog_home',repo_name=c.cs_repo.repo_name,branch=cs.branch))}</span>
46 %endif
46 %endif
47 </td>
47 </td>
48 <td class="expand_commit" commit_id="${cs.raw_id}" title="${_('Expand commit message')}">
48 <td class="expand_commit" commit_id="${cs.raw_id}" title="${_('Expand commit message')}">
49 <i class="icon-resize-vertical" style="color:#DDD"></i>
49 <i class="icon-resize-vertical" style="color:#DDD"></i>
50 </td>
50 </td>
51 <td><div id="C-${cs.raw_id}" class="message">${h.urlify_commit(cs.message, c.repo_name)}</div></td>
51 <td><div id="C-${cs.raw_id}" class="message">${h.urlify_commit(cs.message, c.repo_name)}</div></td>
52 </tr>
52 </tr>
53 %endfor
53 %endfor
54 </table>
54 </table>
55
55
56 </div>
56 </div>
57
57
58 %if c.as_form:
58 %if c.as_form:
59 <div style="font-size:1.1em;font-weight: bold;clear:both;padding-top:10px">
59 <div style="font-size:1.1em;font-weight: bold;clear:both;padding-top:10px">
60 ## links should perhaps use ('rev', c.a_rev) instead ...
60 ## links should perhaps use ('rev', c.a_rev) instead ...
61 ${h.link_to(_('Show merge diff'),
61 ${h.link_to(_('Show merge diff'),
62 h.url('compare_url',
62 h.url('compare_url',
63 repo_name=c.a_repo.repo_name,
63 repo_name=c.a_repo.repo_name,
64 org_ref_type=c.a_ref_type, org_ref_name=c.a_ref_name,
64 org_ref_type=c.a_ref_type, org_ref_name=c.a_ref_name,
65 other_repo=c.cs_repo.repo_name,
65 other_repo=c.cs_repo.repo_name,
66 other_ref_type=c.cs_ref_type, other_ref_name=c.cs_ref_name,
66 other_ref_type=c.cs_ref_type, other_ref_name=c.cs_ref_name,
67 merge='1'),
67 merge='1')
68 )}
68 )}
69 </div>
69 </div>
70 <div style="font-size:1.1em;font-weight: bold;clear:both;padding-top:10px">
70 <div style="font-size:1.1em;font-weight: bold;clear:both;padding-top:10px">
71 ${_('Common ancestor')}:
71 ${_('Common ancestor')}:
72 %if c.ancestor:
72 %if c.ancestor:
73 ${h.link_to(h.short_id(c.ancestor),h.url('changeset_home',repo_name=c.repo_name,revision=c.ancestor))}
73 ${h.link_to(h.short_id(c.ancestor),h.url('changeset_home',repo_name=c.repo_name,revision=c.ancestor))}
74 %else:
74 %else:
75 ${_('No common ancestor found - repositories are unrelated')}
75 ${_('No common ancestor found - repositories are unrelated')}
76 %endif
76 %endif
77 </div>
77 </div>
78 %endif
78 %endif
79 %if c.cs_ranges_org is not None:
79 %if c.cs_ranges_org is not None:
80 ## TODO: list actual changesets?
80 ## TODO: list actual changesets?
81 <div style="font-size:1.1em;font-weight: bold;clear:both;padding-top:10px">
81 <div style="font-size:1.1em;font-weight: bold;clear:both;padding-top:10px">
82 ${h.link_to_ref(c.cs_repo.repo_name, c.cs_ref_type, c.cs_ref_name, c.cs_rev)}
82 ${h.link_to_ref(c.cs_repo.repo_name, c.cs_ref_type, c.cs_ref_name, c.cs_rev)}
83 ${_('is')}
83 ${_('is')}
84 <a href="${c.swap_url}">${_('%s changesets') % (len(c.cs_ranges_org))}</a>
84 <a href="${c.swap_url}">${_('%s changesets') % (len(c.cs_ranges_org))}</a>
85 ${_('behind')}
85 ${_('behind')}
86 ${h.link_to_ref(c.a_repo.repo_name, c.a_ref_type, c.a_ref_name)}
86 ${h.link_to_ref(c.a_repo.repo_name, c.a_ref_type, c.a_ref_name)}
87 </div>
87 </div>
88 %endif
88 %endif
89 %endif
89 %endif
90 </div>
90 </div>
91
91
92 %if c.as_form:
92 %if c.as_form:
93 <div id="jsdata" style="display:none">${c.jsdata|n}</div>
93 <div id="jsdata" style="display:none">${c.jsdata|n}</div>
94 %else:
94 %else:
95 <script type="text/javascript" src="${h.url('/js/graph.js')}"></script>
95 <script type="text/javascript" src="${h.url('/js/graph.js')}"></script>
96 %endif
96 %endif
97
97
98 <script type="text/javascript">
98 <script type="text/javascript">
99
99
100 $(document).ready(function(){
100 $(document).ready(function(){
101 %if not c.as_form:
101 %if not c.as_form:
102 var jsdata = ${c.jsdata|n};
102 var jsdata = ${c.jsdata|n};
103 var r = new BranchRenderer('graph_canvas', 'graph_content_pr');
103 var r = new BranchRenderer('graph_canvas', 'graph_content_pr');
104 r.render(jsdata,100);
104 r.render(jsdata,100);
105 %endif
105 %endif
106
106
107 $('.expand_commit').click(function(e){
107 $('.expand_commit').click(function(e){
108 var cid = $(this).attr('commit_id');
108 var cid = $(this).attr('commit_id');
109 $('#C-'+cid).toggleClass('expanded');
109 $('#C-'+cid).toggleClass('expanded');
110 r.render(jsdata,100);
110 r.render(jsdata,100);
111 });
111 });
112
112
113 $('.gravatar').click(function(e){
113 $('.gravatar').click(function(e){
114 var cid = $(this).attr('commit_id');
114 var cid = $(this).attr('commit_id');
115 $('#row-'+cid).toggleClass('hl', !$('#row-'+cid).hasClass('hl'));
115 $('#row-'+cid).toggleClass('hl', !$('#row-'+cid).hasClass('hl'));
116 });
116 });
117 });
117 });
118
118
119 </script>
119 </script>
@@ -1,209 +1,209 b''
1 ## -*- coding: utf-8 -*-
1 ## -*- coding: utf-8 -*-
2 <%inherit file="/base/base.html"/>
2 <%inherit file="/base/base.html"/>
3
3
4 <%def name="title()">
4 <%def name="title()">
5 %if c.compare_home:
5 %if c.compare_home:
6 ${_('%s Compare') % c.repo_name}
6 ${_('%s Compare') % c.repo_name}
7 %else:
7 %else:
8 ${_('%s Compare') % c.repo_name} - ${'%s@%s' % (c.a_repo.repo_name, c.a_ref_name)} &gt; ${'%s@%s' % (c.cs_repo.repo_name, c.cs_ref_name)}
8 ${_('%s Compare') % c.repo_name} - ${'%s@%s' % (c.a_repo.repo_name, c.a_ref_name)} &gt; ${'%s@%s' % (c.cs_repo.repo_name, c.cs_ref_name)}
9 %endif
9 %endif
10 %if c.site_name:
10 %if c.site_name:
11 &middot; ${c.site_name}
11 &middot; ${c.site_name}
12 %endif
12 %endif
13 </%def>
13 </%def>
14
14
15 <%def name="breadcrumbs_links()">
15 <%def name="breadcrumbs_links()">
16 ${_('Compare revisions')}
16 ${_('Compare revisions')}
17 </%def>
17 </%def>
18
18
19 <%def name="page_nav()">
19 <%def name="page_nav()">
20 ${self.menu('repositories')}
20 ${self.menu('repositories')}
21 </%def>
21 </%def>
22
22
23 <%def name="main()">
23 <%def name="main()">
24 ${self.repo_context_bar('changelog')}
24 ${self.repo_context_bar('changelog')}
25 <div class="box">
25 <div class="box">
26 <!-- box / title -->
26 <!-- box / title -->
27 <div class="title">
27 <div class="title">
28 ${self.breadcrumbs()}
28 ${self.breadcrumbs()}
29 </div>
29 </div>
30 <div class="table">
30 <div class="table">
31 <div id="body" class="diffblock">
31 <div id="body" class="diffblock">
32 <div class="code-header">
32 <div class="code-header">
33 <div>
33 <div>
34 ${h.hidden('compare_org')} <i class="icon-ellipsis-horizontal" style="color: #999; vertical-align: -12px; padding: 0px 0px 0px 2px"></i> ${h.hidden('compare_other')}
34 ${h.hidden('compare_org')} <i class="icon-ellipsis-horizontal" style="color: #999; vertical-align: -12px; padding: 0px 0px 0px 2px"></i> ${h.hidden('compare_other')}
35 %if not c.compare_home:
35 %if not c.compare_home:
36 <a class="btn btn-small" href="${c.swap_url}"><i class="icon-refresh"></i> ${_('Swap')}</a>
36 <a class="btn btn-small" href="${c.swap_url}"><i class="icon-refresh"></i> ${_('Swap')}</a>
37 %endif
37 %endif
38 <div id="compare_revs" class="btn btn-small"><i class="icon-loop"></i> ${_('Compare Revisions')}</div>
38 <div id="compare_revs" class="btn btn-small"><i class="icon-loop"></i> ${_('Compare Revisions')}</div>
39 </div>
39 </div>
40 </div>
40 </div>
41 </div>
41 </div>
42
42
43 %if c.compare_home:
43 %if c.compare_home:
44 <div id="changeset_compare_view_content">
44 <div id="changeset_compare_view_content">
45 <div style="color:#999;font-size: 18px">${_('Compare revisions, branches, bookmarks or tags.')}</div>
45 <div style="color:#999;font-size: 18px">${_('Compare revisions, branches, bookmarks or tags.')}</div>
46 </div>
46 </div>
47 %else:
47 %else:
48 <div id="changeset_compare_view_content">
48 <div id="changeset_compare_view_content">
49 ##CS
49 ##CS
50 <div style="font-size:1.1em;font-weight: bold;clear:both;padding-top:10px">${ungettext('Showing %s commit','Showing %s commits', len(c.cs_ranges)) % len(c.cs_ranges)}</div>
50 <div style="font-size:1.1em;font-weight: bold;clear:both;padding-top:10px">${ungettext('Showing %s commit','Showing %s commits', len(c.cs_ranges)) % len(c.cs_ranges)}</div>
51 <%include file="compare_cs.html" />
51 <%include file="compare_cs.html" />
52
52
53 ## FILES
53 ## FILES
54 <div style="font-size:1.1em;font-weight: bold;clear:both;padding-top:10px">
54 <div style="font-size:1.1em;font-weight: bold;clear:both;padding-top:10px">
55
55
56 % if c.limited_diff:
56 % if c.limited_diff:
57 ${ungettext('%s file changed', '%s files changed', len(c.files)) % len(c.files)}
57 ${ungettext('%s file changed', '%s files changed', len(c.files)) % len(c.files)}
58 % else:
58 % else:
59 ${ungettext('%s file changed with %s insertions and %s deletions','%s files changed with %s insertions and %s deletions', len(c.files)) % (len(c.files),c.lines_added,c.lines_deleted)}:
59 ${ungettext('%s file changed with %s insertions and %s deletions','%s files changed with %s insertions and %s deletions', len(c.files)) % (len(c.files),c.lines_added,c.lines_deleted)}:
60 %endif
60 %endif
61
61
62 ${c.ignorews_url(request.GET)}
62 ${c.ignorews_url(request.GET)}
63 ${c.context_url(request.GET)}
63 ${c.context_url(request.GET)}
64
64
65 </div>
65 </div>
66 <div class="cs_files">
66 <div class="cs_files">
67 %if not c.files:
67 %if not c.files:
68 <span class="empty_data">${_('No files')}</span>
68 <span class="empty_data">${_('No files')}</span>
69 %endif
69 %endif
70 %for fid, change, f, stat in c.files:
70 %for fid, change, f, stat in c.files:
71 <div class="cs_${change}">
71 <div class="cs_${change}">
72 <div class="node">${h.link_to(h.safe_unicode(f), '#' + fid)}</div>
72 <div class="node">${h.link_to(h.safe_unicode(f), '#' + fid)}</div>
73 <div class="changes">${h.fancy_file_stats(stat)}</div>
73 <div class="changes">${h.fancy_file_stats(stat)}</div>
74 </div>
74 </div>
75 %endfor
75 %endfor
76 </div>
76 </div>
77 % if c.limited_diff:
77 % if c.limited_diff:
78 <h5>${_('Changeset was too big and was cut off...')} <a href="${h.url.current(fulldiff=1, **request.GET.mixed())}">${_('Show full diff')}</a></h5>
78 <h5>${_('Changeset was too big and was cut off...')} <a href="${h.url.current(fulldiff=1, **request.GET.mixed())}">${_('Show full diff')}</a></h5>
79 % endif
79 % endif
80 </div>
80 </div>
81
81
82 ## diff block
82 ## diff block
83 <%namespace name="diff_block" file="/changeset/diff_block.html"/>
83 <%namespace name="diff_block" file="/changeset/diff_block.html"/>
84 ${diff_block.diff_block_js()}
84 ${diff_block.diff_block_js()}
85 %for fid, change, f, stat in c.files:
85 %for fid, change, f, stat in c.files:
86 ${diff_block.diff_block_simple([c.changes[fid]])}
86 ${diff_block.diff_block_simple([c.changes[fid]])}
87 %endfor
87 %endfor
88 % if c.limited_diff:
88 % if c.limited_diff:
89 <h4>${_('Changeset was too big and was cut off...')} <a href="${h.url.current(fulldiff=1, **request.GET.mixed())}">${_('Show full diff')}</a></h4>
89 <h4>${_('Changeset was too big and was cut off...')} <a href="${h.url.current(fulldiff=1, **request.GET.mixed())}">${_('Show full diff')}</a></h4>
90 % endif
90 % endif
91 %endif
91 %endif
92 </div>
92 </div>
93
93
94 </div>
94 </div>
95 <script type="text/javascript">
95 <script type="text/javascript">
96
96
97 $(document).ready(function(){
97 $(document).ready(function(){
98 var cache = {}
98 var cache = {}
99 $("#compare_org").select2({
99 $("#compare_org").select2({
100 placeholder: "${'%s@%s' % (c.a_repo.repo_name, c.a_ref_name)}",
100 placeholder: "${'%s@%s' % (c.a_repo.repo_name, c.a_ref_name)}",
101 formatSelection: function(obj){
101 formatSelection: function(obj){
102 return '{0}@{1}'.format("${c.a_repo.repo_name}", obj.text)
102 return '{0}@{1}'.format("${c.a_repo.repo_name}", obj.text)
103 },
103 },
104 dropdownAutoWidth: true,
104 dropdownAutoWidth: true,
105 query: function(query){
105 query: function(query){
106 var key = 'cache';
106 var key = 'cache';
107 var cached = cache[key] ;
107 var cached = cache[key] ;
108 if(cached) {
108 if(cached) {
109 var data = {results: []};
109 var data = {results: []};
110 //filter results
110 //filter results
111 $.each(cached.results, function(){
111 $.each(cached.results, function(){
112 var section = this.text;
112 var section = this.text;
113 var children = [];
113 var children = [];
114 $.each(this.children, function(){
114 $.each(this.children, function(){
115 if(query.term.length == 0 || this.text.toUpperCase().indexOf(query.term.toUpperCase()) >= 0 ){
115 if(query.term.length == 0 || this.text.toUpperCase().indexOf(query.term.toUpperCase()) >= 0 ){
116 children.push({'id': this.id, 'text': this.text})
116 children.push({'id': this.id, 'text': this.text})
117 }
117 }
118 })
118 })
119 data.results.push({'text': section, 'children': children})
119 data.results.push({'text': section, 'children': children})
120 });
120 });
121 //push the typed in changeset
121 //push the typed in changeset
122 data.results.push({'text':_TM['Specify changeset'],
122 data.results.push({'text':_TM['Specify changeset'],
123 'children': [{'id': query.term, 'text': query.term, 'type': 'rev'}]})
123 'children': [{'id': query.term, 'text': query.term, 'type': 'rev'}]})
124 query.callback(data);
124 query.callback(data);
125 }else{
125 }else{
126 $.ajax({
126 $.ajax({
127 url: pyroutes.url('repo_refs_data', {'repo_name': '${c.a_repo.repo_name}'}),
127 url: pyroutes.url('repo_refs_data', {'repo_name': '${c.a_repo.repo_name}'}),
128 data: {},
128 data: {},
129 dataType: 'json',
129 dataType: 'json',
130 type: 'GET',
130 type: 'GET',
131 success: function(data) {
131 success: function(data) {
132 cache[key] = data;
132 cache[key] = data;
133 query.callback(data);
133 query.callback(data);
134 }
134 }
135 })
135 })
136 }
136 }
137 },
137 }
138 });
138 });
139 $("#compare_other").select2({
139 $("#compare_other").select2({
140 placeholder: "${'%s@%s' % (c.cs_repo.repo_name, c.cs_ref_name)}",
140 placeholder: "${'%s@%s' % (c.cs_repo.repo_name, c.cs_ref_name)}",
141 dropdownAutoWidth: true,
141 dropdownAutoWidth: true,
142 formatSelection: function(obj){
142 formatSelection: function(obj){
143 return '{0}@{1}'.format("${c.cs_repo.repo_name}", obj.text)
143 return '{0}@{1}'.format("${c.cs_repo.repo_name}", obj.text)
144 },
144 },
145 query: function(query){
145 query: function(query){
146 var key = 'cache2';
146 var key = 'cache2';
147 var cached = cache[key] ;
147 var cached = cache[key] ;
148 if(cached) {
148 if(cached) {
149 var data = {results: []};
149 var data = {results: []};
150 //filter results
150 //filter results
151 $.each(cached.results, function(){
151 $.each(cached.results, function(){
152 var section = this.text;
152 var section = this.text;
153 var children = [];
153 var children = [];
154 $.each(this.children, function(){
154 $.each(this.children, function(){
155 if(query.term.length == 0 || this.text.toUpperCase().indexOf(query.term.toUpperCase()) >= 0 ){
155 if(query.term.length == 0 || this.text.toUpperCase().indexOf(query.term.toUpperCase()) >= 0 ){
156 children.push({'id': this.id, 'text': this.text})
156 children.push({'id': this.id, 'text': this.text})
157 }
157 }
158 })
158 })
159 data.results.push({'text': section, 'children': children})
159 data.results.push({'text': section, 'children': children})
160 });
160 });
161 //push the typed in changeset
161 //push the typed in changeset
162 data.results.push({'text':_TM['Specify changeset'],
162 data.results.push({'text':_TM['Specify changeset'],
163 'children': [{'id': query.term, 'text': query.term, 'type': 'rev'}]})
163 'children': [{'id': query.term, 'text': query.term, 'type': 'rev'}]})
164 query.callback(data);
164 query.callback(data);
165 }else{
165 }else{
166 $.ajax({
166 $.ajax({
167 url: pyroutes.url('repo_refs_data', {'repo_name': '${c.cs_repo.repo_name}'}),
167 url: pyroutes.url('repo_refs_data', {'repo_name': '${c.cs_repo.repo_name}'}),
168 data: {},
168 data: {},
169 dataType: 'json',
169 dataType: 'json',
170 type: 'GET',
170 type: 'GET',
171 success: function(data) {
171 success: function(data) {
172 cache[key] = data;
172 cache[key] = data;
173 query.callback({results: data.results});
173 query.callback({results: data.results});
174 }
174 }
175 })
175 })
176 }
176 }
177 },
177 }
178 });
178 });
179
179
180 var values_changed = function() {
180 var values_changed = function() {
181 var values = $('#compare_org').select2('data') && $('#compare_other').select2('data');
181 var values = $('#compare_org').select2('data') && $('#compare_other').select2('data');
182 if (values) {
182 if (values) {
183 $('#compare_revs').removeClass("disabled");
183 $('#compare_revs').removeClass("disabled");
184 // TODO: the swap button ... if any
184 // TODO: the swap button ... if any
185 } else {
185 } else {
186 $('#compare_revs').addClass("disabled");
186 $('#compare_revs').addClass("disabled");
187 // TODO: the swap button ... if any
187 // TODO: the swap button ... if any
188 }
188 }
189 }
189 }
190 values_changed();
190 values_changed();
191 $('#compare_org').change(values_changed);
191 $('#compare_org').change(values_changed);
192 $('#compare_other').change(values_changed);
192 $('#compare_other').change(values_changed);
193 $('#compare_revs').on('click', function(e){
193 $('#compare_revs').on('click', function(e){
194 var org = $('#compare_org').select2('data');
194 var org = $('#compare_org').select2('data');
195 var other = $('#compare_other').select2('data');
195 var other = $('#compare_other').select2('data');
196 if (!org || !other) {
196 if (!org || !other) {
197 return;
197 return;
198 }
198 }
199
199
200 var compare_url = "${h.url('compare_url',repo_name=c.repo_name,org_ref_type='__other_ref_type__',org_ref_name='__org__',other_ref_type='__org_ref_type__',other_ref_name='__other__', other_repo=c.cs_repo.repo_name)}";
200 var compare_url = "${h.url('compare_url',repo_name=c.repo_name,org_ref_type='__other_ref_type__',org_ref_name='__org__',other_ref_type='__org_ref_type__',other_ref_name='__other__', other_repo=c.cs_repo.repo_name)}";
201 var u = compare_url.replace('__other_ref_type__',org.type)
201 var u = compare_url.replace('__other_ref_type__',org.type)
202 .replace('__org__',org.text)
202 .replace('__org__',org.text)
203 .replace('__org_ref_type__',other.type)
203 .replace('__org_ref_type__',other.type)
204 .replace('__other__',other.text);
204 .replace('__other__',other.text);
205 window.location = u;
205 window.location = u;
206 });
206 });
207 });
207 });
208 </script>
208 </script>
209 </%def>
209 </%def>
@@ -1,112 +1,112 b''
1 ## -*- coding: utf-8 -*-
1 ## -*- coding: utf-8 -*-
2
2
3 <%inherit file="/base/base.html"/>
3 <%inherit file="/base/base.html"/>
4
4
5 <%def name="js_extra()">
5 <%def name="js_extra()">
6 <script type="text/javascript" src="${h.url('/js/codemirror.js')}"></script>
6 <script type="text/javascript" src="${h.url('/js/codemirror.js')}"></script>
7 <script type="text/javascript" src="${h.url('/js/mergely.js')}"></script>
7 <script type="text/javascript" src="${h.url('/js/mergely.js')}"></script>
8 </%def>
8 </%def>
9 <%def name="css_extra()">
9 <%def name="css_extra()">
10 <link rel="stylesheet" type="text/css" href="${h.url('/css/codemirror.css')}"/>
10 <link rel="stylesheet" type="text/css" href="${h.url('/css/codemirror.css')}"/>
11 <link rel="stylesheet" type="text/css" href="${h.url('/css/mergely.css')}"/>
11 <link rel="stylesheet" type="text/css" href="${h.url('/css/mergely.css')}"/>
12 </%def>
12 </%def>
13
13
14 <%def name="title()">
14 <%def name="title()">
15 ${_('%s File side-by-side diff') % c.repo_name}
15 ${_('%s File side-by-side diff') % c.repo_name}
16 %if c.site_name:
16 %if c.site_name:
17 &middot; ${c.site_name}
17 &middot; ${c.site_name}
18 %endif
18 %endif
19 </%def>
19 </%def>
20
20
21 <%def name="breadcrumbs_links()">
21 <%def name="breadcrumbs_links()">
22 ${_('File diff')} ${h.show_id(c.changeset_1)} &rarr; ${h.show_id(c.changeset_2)}
22 ${_('File diff')} ${h.show_id(c.changeset_1)} &rarr; ${h.show_id(c.changeset_2)}
23 </%def>
23 </%def>
24
24
25 <%def name="page_nav()">
25 <%def name="page_nav()">
26 ${self.menu('repositories')}
26 ${self.menu('repositories')}
27 </%def>
27 </%def>
28
28
29 <%def name="main()">
29 <%def name="main()">
30 ${self.repo_context_bar('changelog')}
30 ${self.repo_context_bar('changelog')}
31 <div class="box">
31 <div class="box">
32 <!-- box / title -->
32 <!-- box / title -->
33 <div class="title">
33 <div class="title">
34 ${self.breadcrumbs()}
34 ${self.breadcrumbs()}
35 </div>
35 </div>
36
36
37 <div class="diff-container" style="overflow-x: hidden">
37 <div class="diff-container" style="overflow-x: hidden">
38 <div class="diffblock comm" style="margin:3px; padding:1px">
38 <div class="diffblock comm" style="margin:3px; padding:1px">
39 <div class="code-header">
39 <div class="code-header">
40 <div class="changeset_header">
40 <div class="changeset_header">
41 <div class="changeset_file">
41 <div class="changeset_file">
42 ${h.link_to(h.safe_unicode(c.node1.path),h.url('files_home',repo_name=c.repo_name,
42 ${h.link_to(h.safe_unicode(c.node1.path),h.url('files_home',repo_name=c.repo_name,
43 revision=c.cs2.raw_id,f_path=h.safe_unicode(c.node1.path)))}
43 revision=c.cs2.raw_id,f_path=h.safe_unicode(c.node1.path)))}
44 </div>
44 </div>
45 <div class="diff-actions">
45 <div class="diff-actions">
46 <a href="${h.url('files_diff_home',repo_name=c.repo_name,f_path=h.safe_unicode(c.node1.path),diff2=c.cs2.raw_id,diff1=c.cs1.raw_id,diff='diff',fulldiff=1)}" class="tooltip" title="${h.tooltip(_('Show full diff for this file'))}">
46 <a href="${h.url('files_diff_home',repo_name=c.repo_name,f_path=h.safe_unicode(c.node1.path),diff2=c.cs2.raw_id,diff1=c.cs1.raw_id,diff='diff',fulldiff=1)}" class="tooltip" title="${h.tooltip(_('Show full diff for this file'))}">
47 <img class="icon" src="${h.url('/images/icons/page_white_go.png')}"/>
47 <img class="icon" src="${h.url('/images/icons/page_white_go.png')}"/>
48 </a>
48 </a>
49 <a href="${h.url('files_diff_2way_home',repo_name=c.repo_name,f_path=h.safe_unicode(c.node1.path),diff2=c.cs2.raw_id,diff1=c.cs1.raw_id,diff='diff',fulldiff=1)}" class="tooltip" title="${h.tooltip(_('Show full side-by-side diff for this file'))}">
49 <a href="${h.url('files_diff_2way_home',repo_name=c.repo_name,f_path=h.safe_unicode(c.node1.path),diff2=c.cs2.raw_id,diff1=c.cs1.raw_id,diff='diff',fulldiff=1)}" class="tooltip" title="${h.tooltip(_('Show full side-by-side diff for this file'))}">
50 <img class="icon" src="${h.url('/images/icons/application_double.png')}"/>
50 <img class="icon" src="${h.url('/images/icons/application_double.png')}"/>
51 </a>
51 </a>
52 <a href="${h.url('files_diff_home',repo_name=c.repo_name,f_path=h.safe_unicode(c.node1.path),diff2=c.cs2.raw_id,diff1=c.cs1.raw_id,diff='raw')}" class="tooltip" title="${h.tooltip(_('Raw diff'))}">
52 <a href="${h.url('files_diff_home',repo_name=c.repo_name,f_path=h.safe_unicode(c.node1.path),diff2=c.cs2.raw_id,diff1=c.cs1.raw_id,diff='raw')}" class="tooltip" title="${h.tooltip(_('Raw diff'))}">
53 <img class="icon" src="${h.url('/images/icons/page_white.png')}"/>
53 <img class="icon" src="${h.url('/images/icons/page_white.png')}"/>
54 </a>
54 </a>
55 <a href="${h.url('files_diff_home',repo_name=c.repo_name,f_path=h.safe_unicode(c.node1.path),diff2=c.cs2.raw_id,diff1=c.cs1.raw_id,diff='download')}" class="tooltip" title="${h.tooltip(_('Download diff'))}">
55 <a href="${h.url('files_diff_home',repo_name=c.repo_name,f_path=h.safe_unicode(c.node1.path),diff2=c.cs2.raw_id,diff1=c.cs1.raw_id,diff='download')}" class="tooltip" title="${h.tooltip(_('Download diff'))}">
56 <img class="icon" src="${h.url('/images/icons/page_save.png')}"/>
56 <img class="icon" src="${h.url('/images/icons/page_save.png')}"/>
57 </a>
57 </a>
58 ${h.checkbox('ignorews', label=_('Ignore whitespace'))}
58 ${h.checkbox('ignorews', label=_('Ignore whitespace'))}
59 ${h.checkbox('edit_mode', label=_('Edit'))}
59 ${h.checkbox('edit_mode', label=_('Edit'))}
60 </div>
60 </div>
61 </div>
61 </div>
62 </div>
62 </div>
63 <div id="compare"></div>
63 <div id="compare"></div>
64 </div>
64 </div>
65 </div>
65 </div>
66
66
67 <script>
67 <script>
68 var orig1_url = '${h.url('files_raw_home',repo_name=c.repo_name,f_path=h.safe_unicode(c.node1.path),revision=c.cs1.raw_id)}';
68 var orig1_url = '${h.url('files_raw_home',repo_name=c.repo_name,f_path=h.safe_unicode(c.node1.path),revision=c.cs1.raw_id)}';
69 var orig2_url = '${h.url('files_raw_home',repo_name=c.repo_name,f_path=h.safe_unicode(c.node2.path),revision=c.cs2.raw_id)}';
69 var orig2_url = '${h.url('files_raw_home',repo_name=c.repo_name,f_path=h.safe_unicode(c.node2.path),revision=c.cs2.raw_id)}';
70
70
71 $(document).ready(function () {
71 $(document).ready(function () {
72 $('#compare').mergely({
72 $('#compare').mergely({
73 width: 'auto',
73 width: 'auto',
74 height: '600',
74 height: '600',
75 fgcolor: {a:'#ddffdd',c:'#cccccc',d:'#ffdddd'},
75 fgcolor: {a:'#ddffdd',c:'#cccccc',d:'#ffdddd'},
76 bgcolor: '#fff',
76 bgcolor: '#fff',
77 viewport: true,
77 viewport: true,
78 cmsettings: {mode: 'text/plain', readOnly: true, lineWrapping: false, lineNumbers: true},
78 cmsettings: {mode: 'text/plain', readOnly: true, lineWrapping: false, lineNumbers: true},
79 lhs: function(setValue) {
79 lhs: function(setValue) {
80 if("${c.node1.is_binary}" == "True"){
80 if("${c.node1.is_binary}" == "True"){
81 setValue('Binary file')
81 setValue('Binary file')
82 }
82 }
83 else{
83 else{
84 $.ajax(orig1_url, {dataType: 'text', success: setValue});
84 $.ajax(orig1_url, {dataType: 'text', success: setValue});
85 }
85 }
86
86
87 },
87 },
88 rhs: function(setValue) {
88 rhs: function(setValue) {
89 if("${c.node2.is_binary}" == "True"){
89 if("${c.node2.is_binary}" == "True"){
90 setValue('Binary file')
90 setValue('Binary file')
91 }
91 }
92 else{
92 else{
93 $.ajax(orig2_url, {dataType: 'text', success: setValue});
93 $.ajax(orig2_url, {dataType: 'text', success: setValue});
94 }
94 }
95 },
95 }
96 });
96 });
97 $('#ignorews').change(function(e){
97 $('#ignorews').change(function(e){
98 var val = e.currentTarget.checked;
98 var val = e.currentTarget.checked;
99 $('#compare').mergely('options', {ignorews: val});
99 $('#compare').mergely('options', {ignorews: val});
100 $('#compare').mergely('update');
100 $('#compare').mergely('update');
101 })
101 })
102 $('#edit_mode').change(function(e){
102 $('#edit_mode').change(function(e){
103 var val = !e.currentTarget.checked;
103 var val = !e.currentTarget.checked;
104 $('#compare').mergely('cm', 'lhs').setOption('readOnly', val);
104 $('#compare').mergely('cm', 'lhs').setOption('readOnly', val);
105 $('#compare').mergely('cm', 'rhs').setOption('readOnly', val);
105 $('#compare').mergely('cm', 'rhs').setOption('readOnly', val);
106 $('#compare').mergely('update');
106 $('#compare').mergely('update');
107 })
107 })
108 });
108 });
109 </script>
109 </script>
110
110
111 </div>
111 </div>
112 </%def>
112 </%def>
@@ -1,257 +1,257 b''
1 <%inherit file="/base/base.html"/>
1 <%inherit file="/base/base.html"/>
2
2
3 <%def name="title(*args)">
3 <%def name="title(*args)">
4 ${_('%s Files') % c.repo_name}
4 ${_('%s Files') % c.repo_name}
5 %if hasattr(c,'file'):
5 %if hasattr(c,'file'):
6 &middot; ${h.safe_unicode(c.file.path) or '\\'}
6 &middot; ${h.safe_unicode(c.file.path) or '\\'}
7 %endif
7 %endif
8
8
9 %if c.site_name:
9 %if c.site_name:
10 &middot; ${c.site_name}
10 &middot; ${c.site_name}
11 %endif
11 %endif
12 </%def>
12 </%def>
13
13
14 <%def name="breadcrumbs_links()">
14 <%def name="breadcrumbs_links()">
15 ${_('Files')}
15 ${_('Files')}
16 %if c.file:
16 %if c.file:
17 @ ${h.show_id(c.changeset)}
17 @ ${h.show_id(c.changeset)}
18 %endif
18 %endif
19 </%def>
19 </%def>
20
20
21 <%def name="page_nav()">
21 <%def name="page_nav()">
22 ${self.menu('repositories')}
22 ${self.menu('repositories')}
23 </%def>
23 </%def>
24
24
25 <%def name="main()">
25 <%def name="main()">
26 ${self.repo_context_bar('files', c.revision)}
26 ${self.repo_context_bar('files', c.revision)}
27 <div class="box">
27 <div class="box">
28 <!-- box / title -->
28 <!-- box / title -->
29 <div class="title">
29 <div class="title">
30 ${self.breadcrumbs()}
30 ${self.breadcrumbs()}
31 <ul class="links">
31 <ul class="links">
32 <li style="color:white">
32 <li style="color:white">
33 ${_("Branch filter:")} ${h.select('branch_selector',c.changeset.raw_id,c.revision_options)}
33 ${_("Branch filter:")} ${h.select('branch_selector',c.changeset.raw_id,c.revision_options)}
34 </li>
34 </li>
35 </ul>
35 </ul>
36 </div>
36 </div>
37 <div class="table">
37 <div class="table">
38 <div id="files_data">
38 <div id="files_data">
39 <%include file='files_ypjax.html'/>
39 <%include file='files_ypjax.html'/>
40 </div>
40 </div>
41 </div>
41 </div>
42 </div>
42 </div>
43
43
44 <script type="text/javascript">
44 <script type="text/javascript">
45 var CACHE = {};
45 var CACHE = {};
46 var CACHE_EXPIRE = 5*60*1000; //cache for 5*60s
46 var CACHE_EXPIRE = 5*60*1000; //cache for 5*60s
47 //used to construct links from the search list
47 //used to construct links from the search list
48 var url_base = '${h.url("files_home",repo_name=c.repo_name,revision='__REV__',f_path='__FPATH__')}';
48 var url_base = '${h.url("files_home",repo_name=c.repo_name,revision='__REV__',f_path='__FPATH__')}';
49 //send the nodelist request to this url
49 //send the nodelist request to this url
50 var node_list_url = '${h.url("files_nodelist_home",repo_name=c.repo_name,revision='__REV__',f_path='__FPATH__')}';
50 var node_list_url = '${h.url("files_nodelist_home",repo_name=c.repo_name,revision='__REV__',f_path='__FPATH__')}';
51 // send the node history requst to this url
51 // send the node history requst to this url
52 var node_history_url = '${h.url("files_history_home",repo_name=c.repo_name,revision='__REV__',f_path='__FPATH__')}';
52 var node_history_url = '${h.url("files_history_home",repo_name=c.repo_name,revision='__REV__',f_path='__FPATH__')}';
53
53
54 ## new pyroutes URLs
54 ## new pyroutes URLs
55 pyroutes.register('files_nodelist_home', "${h.url('files_nodelist_home', repo_name=c.repo_name,revision='%(revision)s',f_path='%(f_path)s')}", ['revision', 'f_path']);
55 pyroutes.register('files_nodelist_home', "${h.url('files_nodelist_home', repo_name=c.repo_name,revision='%(revision)s',f_path='%(f_path)s')}", ['revision', 'f_path']);
56 pyroutes.register('files_history_home', "${h.url('files_history_home', repo_name=c.repo_name,revision='%(revision)s',f_path='%(f_path)s')}", ['revision', 'f_path']);
56 pyroutes.register('files_history_home', "${h.url('files_history_home', repo_name=c.repo_name,revision='%(revision)s',f_path='%(f_path)s')}", ['revision', 'f_path']);
57 pyroutes.register('files_authors_home', "${h.url('files_authors_home', repo_name=c.repo_name,revision='%(revision)s',f_path='%(f_path)s')}", ['revision', 'f_path']);
57 pyroutes.register('files_authors_home', "${h.url('files_authors_home', repo_name=c.repo_name,revision='%(revision)s',f_path='%(f_path)s')}", ['revision', 'f_path']);
58
58
59 var ypjax_links = function(){
59 var ypjax_links = function(){
60 $('.ypjax-link').click(function(e){
60 $('.ypjax-link').click(function(e){
61
61
62 //don't do ypjax on middle click
62 //don't do ypjax on middle click
63 if(e.which == 2 || !History.enabled){
63 if(e.which == 2 || !History.enabled){
64 return true;
64 return true;
65 }
65 }
66
66
67 var el = e.currentTarget;
67 var el = e.currentTarget;
68 var url = el.href;
68 var url = el.href;
69
69
70 var _base_url = '${h.url("files_home",repo_name=c.repo_name,revision='',f_path='')}';
70 var _base_url = '${h.url("files_home",repo_name=c.repo_name,revision='',f_path='')}';
71 _base_url = _base_url.replace('//','/')
71 _base_url = _base_url.replace('//','/')
72
72
73 //extract rev and the f_path from url.
73 //extract rev and the f_path from url.
74 parts = url.split(_base_url)
74 parts = url.split(_base_url)
75 if(parts.length != 2){
75 if(parts.length != 2){
76 return false;
76 return false;
77 }
77 }
78
78
79 var parts2 = parts[1].split('/');
79 var parts2 = parts[1].split('/');
80 var rev = parts2.shift(); // pop the first element which is the revision
80 var rev = parts2.shift(); // pop the first element which is the revision
81 var f_path = parts2.join('/');
81 var f_path = parts2.join('/');
82
82
83 //page title make this consistent with title() mako function on top
83 //page title make this consistent with title() mako function on top
84 var title = "${_('%s Files') % c.repo_name}" + " &middot; " + (f_path || '\\') + " &middot; " + "${c.site_name}";
84 var title = "${_('%s Files') % c.repo_name}" + " &middot; " + (f_path || '\\') + " &middot; " + "${c.site_name}";
85
85
86 var _node_list_url = node_list_url.replace('__REV__',rev).replace('__FPATH__', f_path);
86 var _node_list_url = node_list_url.replace('__REV__',rev).replace('__FPATH__', f_path);
87 var _url_base = url_base.replace('__REV__',rev);
87 var _url_base = url_base.replace('__REV__',rev);
88
88
89 // Change our States and save some data for handling events
89 // Change our States and save some data for handling events
90 var data = {url:url,title:title, url_base:_url_base,
90 var data = {url:url,title:title, url_base:_url_base,
91 node_list_url:_node_list_url, rev:rev, f_path:f_path};
91 node_list_url:_node_list_url, rev:rev, f_path:f_path};
92 History.pushState(data, title, url);
92 History.pushState(data, title, url);
93
93
94 //now we're sure that we can do ypjax things
94 //now we're sure that we can do ypjax things
95 e.preventDefault();
95 e.preventDefault();
96 return false;
96 return false;
97 });
97 });
98 }
98 }
99
99
100 // callbacks needed to process the pjax filebrowser
100 // callbacks needed to process the pjax filebrowser
101 var callbacks = function(State){
101 var callbacks = function(State){
102 ypjax_links();
102 ypjax_links();
103 tooltip_activate();
103 tooltip_activate();
104
104
105 if(State !== undefined){
105 if(State !== undefined){
106 //inistially loaded stuff
106 //inistially loaded stuff
107 var _f_path = State.data.f_path;
107 var _f_path = State.data.f_path;
108 var _rev = State.data.rev;
108 var _rev = State.data.rev;
109
109
110 fileBrowserListeners(State.url, State.data.node_list_url, State.data.url_base);
110 fileBrowserListeners(State.url, State.data.node_list_url, State.data.url_base);
111 // Inform Google Analytics of the change
111 // Inform Google Analytics of the change
112 if ( typeof window.pageTracker !== 'undefined' ) {
112 if ( typeof window.pageTracker !== 'undefined' ) {
113 window.pageTracker._trackPageview(State.url);
113 window.pageTracker._trackPageview(State.url);
114 }
114 }
115 }
115 }
116
116
117 function highlight_lines(lines){
117 function highlight_lines(lines){
118 for(pos in lines){
118 for(pos in lines){
119 $('#L'+lines[pos]).css('background-color','#FFFFBE');
119 $('#L'+lines[pos]).css('background-color','#FFFFBE');
120 }
120 }
121 }
121 }
122 page_highlights = location.href.substring(location.href.indexOf('#')+1).split('L');
122 page_highlights = location.href.substring(location.href.indexOf('#')+1).split('L');
123 if (page_highlights.length == 2){
123 if (page_highlights.length == 2){
124 highlight_ranges = page_highlights[1].split(",");
124 highlight_ranges = page_highlights[1].split(",");
125
125
126 var h_lines = [];
126 var h_lines = [];
127 for (pos in highlight_ranges){
127 for (pos in highlight_ranges){
128 var _range = highlight_ranges[pos].split('-');
128 var _range = highlight_ranges[pos].split('-');
129 if(_range.length == 2){
129 if(_range.length == 2){
130 var start = parseInt(_range[0]);
130 var start = parseInt(_range[0]);
131 var end = parseInt(_range[1]);
131 var end = parseInt(_range[1]);
132 if (start < end){
132 if (start < end){
133 for(var i=start;i<=end;i++){
133 for(var i=start;i<=end;i++){
134 h_lines.push(i);
134 h_lines.push(i);
135 }
135 }
136 }
136 }
137 }
137 }
138 else{
138 else{
139 h_lines.push(parseInt(highlight_ranges[pos]));
139 h_lines.push(parseInt(highlight_ranges[pos]));
140 }
140 }
141 }
141 }
142 highlight_lines(h_lines);
142 highlight_lines(h_lines);
143 $('#L'+h_lines[0]).each(function(){
143 $('#L'+h_lines[0]).each(function(){
144 this.scrollIntoView();
144 this.scrollIntoView();
145 });
145 });
146 }
146 }
147
147
148 // select code link event
148 // select code link event
149 $('#hlcode').mouseup(getSelectionLink);
149 $('#hlcode').mouseup(getSelectionLink);
150
150
151 // history select field
151 // history select field
152 var cache = {}
152 var cache = {}
153 $("#diff1").select2({
153 $("#diff1").select2({
154 placeholder: _TM['Select changeset'],
154 placeholder: _TM['Select changeset'],
155 dropdownAutoWidth: true,
155 dropdownAutoWidth: true,
156 query: function(query){
156 query: function(query){
157 var key = 'cache';
157 var key = 'cache';
158 var cached = cache[key] ;
158 var cached = cache[key] ;
159 if(cached) {
159 if(cached) {
160 var data = {results: []};
160 var data = {results: []};
161 //filter results
161 //filter results
162 $.each(cached.results, function(){
162 $.each(cached.results, function(){
163 var section = this.text;
163 var section = this.text;
164 var children = [];
164 var children = [];
165 $.each(this.children, function(){
165 $.each(this.children, function(){
166 if(query.term.length == 0 || this.text.toUpperCase().indexOf(query.term.toUpperCase()) >= 0 ){
166 if(query.term.length == 0 || this.text.toUpperCase().indexOf(query.term.toUpperCase()) >= 0 ){
167 children.push({'id': this.id, 'text': this.text})
167 children.push({'id': this.id, 'text': this.text})
168 }
168 }
169 })
169 })
170 data.results.push({'text': section, 'children': children})
170 data.results.push({'text': section, 'children': children})
171 });
171 });
172 query.callback(data);
172 query.callback(data);
173 }else{
173 }else{
174 $.ajax({
174 $.ajax({
175 url: pyroutes.url('files_history_home', {'revision': _rev, 'f_path': _f_path}),
175 url: pyroutes.url('files_history_home', {'revision': _rev, 'f_path': _f_path}),
176 data: {},
176 data: {},
177 dataType: 'json',
177 dataType: 'json',
178 type: 'GET',
178 type: 'GET',
179 success: function(data) {
179 success: function(data) {
180 cache[key] = data;
180 cache[key] = data;
181 query.callback({results: data.results});
181 query.callback({results: data.results});
182 }
182 }
183 })
183 })
184 }
184 }
185 },
185 }
186 });
186 });
187 $('#show_authors').on('click', function(){
187 $('#show_authors').on('click', function(){
188 $.ajax({
188 $.ajax({
189 url: pyroutes.url('files_authors_home', {'revision': _rev, 'f_path': _f_path}),
189 url: pyroutes.url('files_authors_home', {'revision': _rev, 'f_path': _f_path}),
190 success: function(data) {
190 success: function(data) {
191 $('#file_authors').html(data);
191 $('#file_authors').html(data);
192 $('#file_authors').show();
192 $('#file_authors').show();
193 tooltip_activate()
193 tooltip_activate()
194 }
194 }
195 })
195 })
196 })
196 })
197 }
197 }
198
198
199 $(document).ready(function(){
199 $(document).ready(function(){
200 ypjax_links();
200 ypjax_links();
201 var $files_data = $('#files_data');
201 var $files_data = $('#files_data');
202 //Bind to StateChange Event
202 //Bind to StateChange Event
203 History.Adapter.bind(window,'statechange',function(){
203 History.Adapter.bind(window,'statechange',function(){
204 var State = History.getState();
204 var State = History.getState();
205 cache_key = State.url;
205 cache_key = State.url;
206 //check if we have this request in cache maybe ?
206 //check if we have this request in cache maybe ?
207 var _cache_obj = CACHE[cache_key];
207 var _cache_obj = CACHE[cache_key];
208 var _cur_time = new Date().getTime();
208 var _cur_time = new Date().getTime();
209 // get from cache if it's there and not yet expired !
209 // get from cache if it's there and not yet expired !
210 if(_cache_obj !== undefined && _cache_obj[0] > _cur_time){
210 if(_cache_obj !== undefined && _cache_obj[0] > _cur_time){
211 $files_data.html(_cache_obj[1]);
211 $files_data.html(_cache_obj[1]);
212 $files_data.css('opacity','1.0');
212 $files_data.css('opacity','1.0');
213 //callbacks after ypjax call
213 //callbacks after ypjax call
214 callbacks(State);
214 callbacks(State);
215 }
215 }
216 else{
216 else{
217 asynchtml(State.url, $files_data, function(){
217 asynchtml(State.url, $files_data, function(){
218 callbacks(State);
218 callbacks(State);
219 var expire_on = new Date().getTime() + CACHE_EXPIRE;
219 var expire_on = new Date().getTime() + CACHE_EXPIRE;
220 CACHE[cache_key] = [expire_on, $files_data.html()];
220 CACHE[cache_key] = [expire_on, $files_data.html()];
221 });
221 });
222 }
222 }
223 });
223 });
224
224
225 // init the search filter
225 // init the search filter
226 var _State = {
226 var _State = {
227 url: "${h.url.current()}",
227 url: "${h.url.current()}",
228 data: {
228 data: {
229 node_list_url: node_list_url.replace('__REV__',"${c.changeset.raw_id}").replace('__FPATH__', "${h.safe_unicode(c.file.path)}"),
229 node_list_url: node_list_url.replace('__REV__',"${c.changeset.raw_id}").replace('__FPATH__', "${h.safe_unicode(c.file.path)}"),
230 url_base: url_base.replace('__REV__',"${c.changeset.raw_id}"),
230 url_base: url_base.replace('__REV__',"${c.changeset.raw_id}"),
231 rev:"${c.changeset.raw_id}",
231 rev:"${c.changeset.raw_id}",
232 f_path: "${h.safe_unicode(c.file.path)}"
232 f_path: "${h.safe_unicode(c.file.path)}"
233 }
233 }
234 }
234 }
235 fileBrowserListeners(_State.url, _State.data.node_list_url, _State.data.url_base);
235 fileBrowserListeners(_State.url, _State.data.node_list_url, _State.data.url_base);
236
236
237 // change branch filter
237 // change branch filter
238 $("#branch_selector").select2({
238 $("#branch_selector").select2({
239 dropdownAutoWidth: true,
239 dropdownAutoWidth: true,
240 minimumInputLength: 1,
240 minimumInputLength: 1
241 });
241 });
242
242
243 $("#branch_selector").change(function(e){
243 $("#branch_selector").change(function(e){
244 var selected = e.currentTarget.options[e.currentTarget.selectedIndex].value;
244 var selected = e.currentTarget.options[e.currentTarget.selectedIndex].value;
245 if(selected && selected != "${c.changeset.raw_id}"){
245 if(selected && selected != "${c.changeset.raw_id}"){
246 window.location = pyroutes.url('files_home', {'repo_name': "${h.safe_unicode(c.repo_name)}", 'revision': selected, 'f_path': "${h.safe_unicode(c.file.path)}"});
246 window.location = pyroutes.url('files_home', {'repo_name': "${h.safe_unicode(c.repo_name)}", 'revision': selected, 'f_path': "${h.safe_unicode(c.file.path)}"});
247 $("#browserblock").hide();
247 $("#browserblock").hide();
248 } else {
248 } else {
249 $("#branch_selector").val("${c.changeset.raw_id}");
249 $("#branch_selector").val("${c.changeset.raw_id}");
250 }
250 }
251 });
251 });
252
252
253 });
253 });
254
254
255 </script>
255 </script>
256
256
257 </%def>
257 </%def>
@@ -1,116 +1,116 b''
1 ## -*- coding: utf-8 -*-
1 ## -*- coding: utf-8 -*-
2 <%inherit file="/base/base.html"/>
2 <%inherit file="/base/base.html"/>
3
3
4 <%def name="title()">
4 <%def name="title()">
5 ${_('Fork repository %s') % c.repo_name}
5 ${_('Fork repository %s') % c.repo_name}
6 %if c.site_name:
6 %if c.site_name:
7 &middot; ${c.site_name}
7 &middot; ${c.site_name}
8 %endif
8 %endif
9 </%def>
9 </%def>
10
10
11 <%def name="breadcrumbs_links()">
11 <%def name="breadcrumbs_links()">
12 ${_('Fork')}
12 ${_('Fork')}
13 </%def>
13 </%def>
14
14
15 <%def name="page_nav()">
15 <%def name="page_nav()">
16 ${self.menu('repositories')}
16 ${self.menu('repositories')}
17 </%def>
17 </%def>
18
18
19 <%def name="main()">
19 <%def name="main()">
20 ${self.repo_context_bar('createfork')}
20 ${self.repo_context_bar('createfork')}
21 <div class="box">
21 <div class="box">
22 <!-- box / title -->
22 <!-- box / title -->
23 ${h.form(url('repo_fork_create_home',repo_name=c.repo_info.repo_name))}
23 ${h.form(url('repo_fork_create_home',repo_name=c.repo_info.repo_name))}
24 <div class="form">
24 <div class="form">
25 <!-- fields -->
25 <!-- fields -->
26 <div class="fields">
26 <div class="fields">
27
27
28 <div class="field">
28 <div class="field">
29 <div class="label">
29 <div class="label">
30 <label for="repo_name">${_('Fork name')}:</label>
30 <label for="repo_name">${_('Fork name')}:</label>
31 </div>
31 </div>
32 <div class="input">
32 <div class="input">
33 ${h.text('repo_name',class_="small")}
33 ${h.text('repo_name',class_="small")}
34 ${h.hidden('repo_type',c.repo_info.repo_type)}
34 ${h.hidden('repo_type',c.repo_info.repo_type)}
35 ${h.hidden('fork_parent_id',c.repo_info.repo_id)}
35 ${h.hidden('fork_parent_id',c.repo_info.repo_id)}
36 </div>
36 </div>
37 </div>
37 </div>
38
38
39 <div class="field">
39 <div class="field">
40 <div class="label label-textarea">
40 <div class="label label-textarea">
41 <label for="description">${_('Description')}:</label>
41 <label for="description">${_('Description')}:</label>
42 </div>
42 </div>
43 <div class="textarea editor">
43 <div class="textarea editor">
44 ${h.textarea('description')}
44 ${h.textarea('description')}
45 <span class="help-block">${_('Keep it short and to the point. Use a README file for longer descriptions.')}</span>
45 <span class="help-block">${_('Keep it short and to the point. Use a README file for longer descriptions.')}</span>
46 </div>
46 </div>
47 </div>
47 </div>
48
48
49 <div class="field">
49 <div class="field">
50 <div class="label">
50 <div class="label">
51 <label for="repo_group">${_('Repository group')}:</label>
51 <label for="repo_group">${_('Repository group')}:</label>
52 </div>
52 </div>
53 <div class="input">
53 <div class="input">
54 ${h.select('repo_group','',c.repo_groups,class_="medium")}
54 ${h.select('repo_group','',c.repo_groups,class_="medium")}
55 <span class="help-block">${_('Optionaly select a group to put this repository into.')}</span>
55 <span class="help-block">${_('Optionaly select a group to put this repository into.')}</span>
56 </div>
56 </div>
57 </div>
57 </div>
58
58
59 <div class="field">
59 <div class="field">
60 <div class="label">
60 <div class="label">
61 <label for="landing_rev">${_('Landing revision')}:</label>
61 <label for="landing_rev">${_('Landing revision')}:</label>
62 </div>
62 </div>
63 <div class="input">
63 <div class="input">
64 ${h.select('landing_rev','',c.landing_revs,class_="medium")}
64 ${h.select('landing_rev','',c.landing_revs,class_="medium")}
65 <span class="help-block">${_('Default revision for files page, downloads, whoosh and readme')}</span>
65 <span class="help-block">${_('Default revision for files page, downloads, whoosh and readme')}</span>
66 </div>
66 </div>
67 </div>
67 </div>
68
68
69 <div class="field">
69 <div class="field">
70 <div class="label label-checkbox">
70 <div class="label label-checkbox">
71 <label for="private">${_('Private')}:</label>
71 <label for="private">${_('Private')}:</label>
72 </div>
72 </div>
73 <div class="checkboxes">
73 <div class="checkboxes">
74 ${h.checkbox('private',value="True")}
74 ${h.checkbox('private',value="True")}
75 <span class="help-block">${_('Private repositories are only visible to people explicitly added as collaborators.')}</span>
75 <span class="help-block">${_('Private repositories are only visible to people explicitly added as collaborators.')}</span>
76 </div>
76 </div>
77 </div>
77 </div>
78 <div class="field">
78 <div class="field">
79 <div class="label label-checkbox">
79 <div class="label label-checkbox">
80 <label for="private">${_('Copy permissions')}:</label>
80 <label for="private">${_('Copy permissions')}:</label>
81 </div>
81 </div>
82 <div class="checkboxes">
82 <div class="checkboxes">
83 ${h.checkbox('copy_permissions',value="True", checked="checked")}
83 ${h.checkbox('copy_permissions',value="True", checked="checked")}
84 <span class="help-block">${_('Copy permissions from forked repository')}</span>
84 <span class="help-block">${_('Copy permissions from forked repository')}</span>
85 </div>
85 </div>
86 </div>
86 </div>
87 %if c.can_update:
87 %if c.can_update:
88 <div class="field">
88 <div class="field">
89 <div class="label label-checkbox">
89 <div class="label label-checkbox">
90 <label for="private">${_('Update after clone')}:</label>
90 <label for="private">${_('Update after clone')}:</label>
91 </div>
91 </div>
92 <div class="checkboxes">
92 <div class="checkboxes">
93 ${h.checkbox('update_after_clone',value="True")}
93 ${h.checkbox('update_after_clone',value="True")}
94 <span class="help-block">${_('Checkout source after making a clone')}</span>
94 <span class="help-block">${_('Checkout source after making a clone')}</span>
95 </div>
95 </div>
96 </div>
96 </div>
97 %endif
97 %endif
98 <div class="buttons">
98 <div class="buttons">
99 ${h.submit('',_('Fork this Repository'),class_="btn")}
99 ${h.submit('',_('Fork this Repository'),class_="btn")}
100 </div>
100 </div>
101 </div>
101 </div>
102 </div>
102 </div>
103 ${h.end_form()}
103 ${h.end_form()}
104 </div>
104 </div>
105 <script>
105 <script>
106 $(document).ready(function(){
106 $(document).ready(function(){
107 $("#repo_group").select2({
107 $("#repo_group").select2({
108 'dropdownAutoWidth': true
108 'dropdownAutoWidth': true
109 });
109 });
110 $("#landing_rev").select2({
110 $("#landing_rev").select2({
111 'minimumResultsForSearch': -1,
111 'minimumResultsForSearch': -1
112 });
112 });
113 $('#repo_name').focus();
113 $('#repo_name').focus();
114 })
114 })
115 </script>
115 </script>
116 </%def>
116 </%def>
@@ -1,187 +1,187 b''
1 <%page args="parent,group_name=''" />
1 <%page args="parent,group_name=''" />
2 <div class="box">
2 <div class="box">
3 <!-- box / title -->
3 <!-- box / title -->
4 <div class="title">
4 <div class="title">
5 <h5>
5 <h5>
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')}
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 </h5>
7 </h5>
8 %if c.authuser.username != 'default':
8 %if c.authuser.username != 'default':
9 <ul class="links">
9 <ul class="links">
10 <li>
10 <li>
11 <%
11 <%
12 gr_name = c.group.group_name if c.group else None
12 gr_name = c.group.group_name if c.group else None
13 # create repositories with write permission on group is set to true
13 # create repositories with write permission on group is set to true
14 create_on_write = h.HasPermissionAny('hg.create.write_on_repogroup.true')()
14 create_on_write = h.HasPermissionAny('hg.create.write_on_repogroup.true')()
15 group_admin = h.HasRepoGroupPermissionAny('group.admin')(gr_name, 'can write into group index page')
15 group_admin = h.HasRepoGroupPermissionAny('group.admin')(gr_name, 'can write into group index page')
16 group_write = h.HasRepoGroupPermissionAny('group.write')(gr_name, 'can write into group index page')
16 group_write = h.HasRepoGroupPermissionAny('group.write')(gr_name, 'can write into group index page')
17 %>
17 %>
18 %if h.HasPermissionAny('hg.admin','hg.create.repository')() or (group_admin or (group_write and create_on_write)):
18 %if h.HasPermissionAny('hg.admin','hg.create.repository')() or (group_admin or (group_write and create_on_write)):
19 %if c.group:
19 %if c.group:
20 <a href="${h.url('new_repo',parent_group=c.group.group_id)}" class="btn btn-small btn-success"><i class="icon-plus"></i> ${_('Add Repository')}</a>
20 <a href="${h.url('new_repo',parent_group=c.group.group_id)}" class="btn btn-small btn-success"><i class="icon-plus"></i> ${_('Add Repository')}</a>
21 %if h.HasPermissionAny('hg.admin')() or h.HasRepoGroupPermissionAny('group.admin')(c.group.group_name):
21 %if h.HasPermissionAny('hg.admin')() or h.HasRepoGroupPermissionAny('group.admin')(c.group.group_name):
22 <a href="${h.url('new_repos_group', parent_group=c.group.group_id)}" class="btn btn-small"><i class="icon-plus"></i> ${_(u'Add Repository Group')}</a>
22 <a href="${h.url('new_repos_group', parent_group=c.group.group_id)}" class="btn btn-small"><i class="icon-plus"></i> ${_(u'Add Repository Group')}</a>
23 %endif
23 %endif
24 %else:
24 %else:
25 <a href="${h.url('new_repo')}" class="btn btn-small btn-success"><i class="icon-plus"></i> ${_('Add Repository')}</a>
25 <a href="${h.url('new_repo')}" class="btn btn-small btn-success"><i class="icon-plus"></i> ${_('Add Repository')}</a>
26 %if h.HasPermissionAny('hg.admin')():
26 %if h.HasPermissionAny('hg.admin')():
27 <a href="${h.url('new_repos_group')}" class="btn btn-small"><i class="icon-plus"></i> ${_(u'Add Repository Group')}</a>
27 <a href="${h.url('new_repos_group')}" class="btn btn-small"><i class="icon-plus"></i> ${_(u'Add Repository Group')}</a>
28 %endif
28 %endif
29 %endif
29 %endif
30 %endif
30 %endif
31 %if c.group and h.HasRepoGroupPermissionAny('group.admin')(c.group.group_name):
31 %if c.group and h.HasRepoGroupPermissionAny('group.admin')(c.group.group_name):
32 <a href="${h.url('edit_repo_group',group_name=c.group.group_name)}" title="${_('You have admin right to this group, and can edit it')}" class="btn btn-small"><i class="icon-pencil"></i> ${_('Edit Repository Group')}</a>
32 <a href="${h.url('edit_repo_group',group_name=c.group.group_name)}" title="${_('You have admin right to this group, and can edit it')}" class="btn btn-small"><i class="icon-pencil"></i> ${_('Edit Repository Group')}</a>
33 %endif
33 %endif
34 </li>
34 </li>
35 </ul>
35 </ul>
36 %endif
36 %endif
37 </div>
37 </div>
38 <!-- end box / title -->
38 <!-- end box / title -->
39 <div class="table">
39 <div class="table">
40 % if c.groups:
40 % if c.groups:
41 <div id='groups_list_wrap' class="yui-skin-sam">
41 <div id='groups_list_wrap' class="yui-skin-sam">
42 <table id="groups_list">
42 <table id="groups_list">
43 <thead>
43 <thead>
44 <tr>
44 <tr>
45 <th class="left"><a href="#">${_('Group Name')}</a></th>
45 <th class="left"><a href="#">${_('Group Name')}</a></th>
46 <th class="left"><a href="#">${_('Description')}</a></th>
46 <th class="left"><a href="#">${_('Description')}</a></th>
47 ##<th class="left"><a href="#">${_('Number of Repositories')}</a></th>
47 ##<th class="left"><a href="#">${_('Number of Repositories')}</a></th>
48 </tr>
48 </tr>
49 </thead>
49 </thead>
50
50
51 ## REPO GROUPS
51 ## REPO GROUPS
52 % for gr in c.groups:
52 % for gr in c.groups:
53 <tr>
53 <tr>
54 <td>
54 <td>
55 <div style="white-space: nowrap">
55 <div style="white-space: nowrap">
56 <a href="${url('repos_group_home',group_name=gr.group_name)}"><i class="icon-folder-close"></i> ${gr.name}</a>
56 <a href="${url('repos_group_home',group_name=gr.group_name)}"><i class="icon-folder-close"></i> ${gr.name}</a>
57 </div>
57 </div>
58 </td>
58 </td>
59 %if c.visual.stylify_metatags:
59 %if c.visual.stylify_metatags:
60 <td>${h.urlify_text(h.desc_stylize(gr.group_description))}</td>
60 <td>${h.urlify_text(h.desc_stylize(gr.group_description))}</td>
61 %else:
61 %else:
62 <td>${gr.group_description}</td>
62 <td>${gr.group_description}</td>
63 %endif
63 %endif
64 ## this is commented out since for multi nested repos can be HEAVY!
64 ## this is commented out since for multi nested repos can be HEAVY!
65 ## in number of executed queries during traversing uncomment at will
65 ## in number of executed queries during traversing uncomment at will
66 ##<td><b>${gr.repositories_recursive_count}</b></td>
66 ##<td><b>${gr.repositories_recursive_count}</b></td>
67 </tr>
67 </tr>
68 % endfor
68 % endfor
69 </table>
69 </table>
70 </div>
70 </div>
71 <div id="group-user-paginator" style="padding: 0px 0px 0px 0px"></div>
71 <div id="group-user-paginator" style="padding: 0px 0px 0px 0px"></div>
72 <div style="height: 20px"></div>
72 <div style="height: 20px"></div>
73 % endif
73 % endif
74 <div id="welcome" style="display:none;text-align:center">
74 <div id="welcome" style="display:none;text-align:center">
75 <h1><a href="${h.url('home')}">${c.site_name} ${c.kallithea_version}</a></h1>
75 <h1><a href="${h.url('home')}">${c.site_name} ${c.kallithea_version}</a></h1>
76 </div>
76 </div>
77 <%cnt=0%>
77 <%cnt=0%>
78 <%namespace name="dt" file="/data_table/_dt_elements.html"/>
78 <%namespace name="dt" file="/data_table/_dt_elements.html"/>
79 <div class="yui-skin-sam" id="repos_list_wrap"></div>
79 <div class="yui-skin-sam" id="repos_list_wrap"></div>
80 <div id="user-paginator" style="padding: 0px 0px 0px 0px"></div>
80 <div id="user-paginator" style="padding: 0px 0px 0px 0px"></div>
81 </div>
81 </div>
82 </div>
82 </div>
83
83
84 <script>
84 <script>
85 var data = ${c.data|n};
85 var data = ${c.data|n};
86 var myDataSource = new YAHOO.util.DataSource(data);
86 var myDataSource = new YAHOO.util.DataSource(data);
87 myDataSource.responseType = YAHOO.util.DataSource.TYPE_JSON;
87 myDataSource.responseType = YAHOO.util.DataSource.TYPE_JSON;
88
88
89 myDataSource.responseSchema = {
89 myDataSource.responseSchema = {
90 resultsList: "records",
90 resultsList: "records",
91 fields: [
91 fields: [
92 {key:"menu"},
92 {key:"menu"},
93 {key:"raw_name"},
93 {key:"raw_name"},
94 {key:"name"},
94 {key:"name"},
95 {key:"desc"},
95 {key:"desc"},
96 {key:"last_change"},
96 {key:"last_change"},
97 {key:"last_changeset"},
97 {key:"last_changeset"},
98 {key:"last_rev_raw"},
98 {key:"last_rev_raw"},
99 {key:"owner"},
99 {key:"owner"},
100 {key:"atom"},
100 {key:"atom"}
101 ]
101 ]
102 };
102 };
103 myDataSource.doBeforeCallback = function(req,raw,res,cb) {
103 myDataSource.doBeforeCallback = function(req,raw,res,cb) {
104 // This is the filter function
104 // This is the filter function
105 var data = res.results || [],
105 var data = res.results || [],
106 filtered = [],
106 filtered = [],
107 i,l;
107 i,l;
108
108
109 if (req) {
109 if (req) {
110 req = req.toLowerCase();
110 req = req.toLowerCase();
111 for (i = 0; i<data.length; i++) {
111 for (i = 0; i<data.length; i++) {
112 var pos = data[i].raw_name.toLowerCase().indexOf(req, ${len(group_name)})
112 var pos = data[i].raw_name.toLowerCase().indexOf(req, ${len(group_name)})
113 if (pos != -1) {
113 if (pos != -1) {
114 filtered.push(data[i]);
114 filtered.push(data[i]);
115 }
115 }
116 }
116 }
117 res.results = filtered;
117 res.results = filtered;
118 }
118 }
119 YUD.get('repo_count').innerHTML = res.results.length;
119 YUD.get('repo_count').innerHTML = res.results.length;
120 return res;
120 return res;
121 }
121 }
122
122
123 // main table sorting
123 // main table sorting
124 var myColumnDefs = [
124 var myColumnDefs = [
125 {key:"menu",label:"",sortable:false,className:"quick_repo_menu hidden"},
125 {key:"menu",label:"",sortable:false,className:"quick_repo_menu hidden"},
126 {key:"name",label:"${_('Name')}",sortable:true,
126 {key:"name",label:"${_('Name')}",sortable:true,
127 sortOptions: { sortFunction: nameSort }},
127 sortOptions: { sortFunction: nameSort }},
128 {key:"desc",label:"${_('Description')}",sortable:true},
128 {key:"desc",label:"${_('Description')}",sortable:true},
129 {key:"last_change",label:"${_('Last Change')}",sortable:true,
129 {key:"last_change",label:"${_('Last Change')}",sortable:true,
130 sortOptions: { sortFunction: ageSort }},
130 sortOptions: { sortFunction: ageSort }},
131 {key:"last_changeset",label:"${_('Tip')}",sortable:true,
131 {key:"last_changeset",label:"${_('Tip')}",sortable:true,
132 sortOptions: { sortFunction: revisionSort }},
132 sortOptions: { sortFunction: revisionSort }},
133 {key:"owner",label:"${_('Owner')}",sortable:true},
133 {key:"owner",label:"${_('Owner')}",sortable:true},
134 {key:"atom",label:"",sortable:false},
134 {key:"atom",label:"",sortable:false}
135 ];
135 ];
136
136
137 var myDataTable = new YAHOO.widget.DataTable("repos_list_wrap", myColumnDefs, myDataSource,{
137 var myDataTable = new YAHOO.widget.DataTable("repos_list_wrap", myColumnDefs, myDataSource,{
138 sortedBy:{key:"name",dir:"asc"},
138 sortedBy:{key:"name",dir:"asc"},
139 paginator: YUI_paginator(${c.visual.dashboard_items},['user-paginator']),
139 paginator: YUI_paginator(${c.visual.dashboard_items},['user-paginator']),
140
140
141 MSG_SORTASC:"${_('Click to sort ascending')}",
141 MSG_SORTASC:"${_('Click to sort ascending')}",
142 MSG_SORTDESC:"${_('Click to sort descending')}",
142 MSG_SORTDESC:"${_('Click to sort descending')}",
143 MSG_EMPTY:"${_('No repositories found.')}",
143 MSG_EMPTY:"${_('No repositories found.')}",
144 MSG_ERROR:"${_('Data error.')}",
144 MSG_ERROR:"${_('Data error.')}",
145 MSG_LOADING:"${_('Loading...')}",
145 MSG_LOADING:"${_('Loading...')}"
146 }
146 }
147 );
147 );
148 myDataTable.subscribe('postRenderEvent',function(oArgs) {
148 myDataTable.subscribe('postRenderEvent',function(oArgs) {
149 tooltip_activate();
149 tooltip_activate();
150 quick_repo_menu();
150 quick_repo_menu();
151 });
151 });
152
152
153 var filterTimeout = null;
153 var filterTimeout = null;
154
154
155 updateFilter = function () {
155 updateFilter = function () {
156 // Reset timeout
156 // Reset timeout
157 filterTimeout = null;
157 filterTimeout = null;
158
158
159 // Reset sort
159 // Reset sort
160 var state = myDataTable.getState();
160 var state = myDataTable.getState();
161 state.sortedBy = {key:'name', dir:YAHOO.widget.DataTable.CLASS_ASC};
161 state.sortedBy = {key:'name', dir:YAHOO.widget.DataTable.CLASS_ASC};
162
162
163 // Get filtered data
163 // Get filtered data
164 myDataSource.sendRequest(YUD.get('q_filter').value,{
164 myDataSource.sendRequest(YUD.get('q_filter').value,{
165 success : myDataTable.onDataReturnInitializeTable,
165 success : myDataTable.onDataReturnInitializeTable,
166 failure : myDataTable.onDataReturnInitializeTable,
166 failure : myDataTable.onDataReturnInitializeTable,
167 scope : myDataTable,
167 scope : myDataTable,
168 argument: state
168 argument: state
169 });
169 });
170
170
171 };
171 };
172 $('#q_filter').click(function(){
172 $('#q_filter').click(function(){
173 if(!$('#q_filter').hasClass('loaded')){
173 if(!$('#q_filter').hasClass('loaded')){
174 //TODO: load here full list later to do search within groups
174 //TODO: load here full list later to do search within groups
175 $('#q_filter').addClass('loaded');
175 $('#q_filter').addClass('loaded');
176 }
176 }
177 });
177 });
178
178
179 $('#q_filter').keyup(function(){
179 $('#q_filter').keyup(function(){
180 clearTimeout(filterTimeout);
180 clearTimeout(filterTimeout);
181 filterTimeout = setTimeout(updateFilter,600);
181 filterTimeout = setTimeout(updateFilter,600);
182 });
182 });
183
183
184 if($('#q_filter').val()) {
184 if($('#q_filter').val()) {
185 updateFilter();
185 updateFilter();
186 }
186 }
187 </script>
187 </script>
@@ -1,339 +1,339 b''
1 ## -*- coding: utf-8 -*-
1 ## -*- coding: utf-8 -*-
2 <%inherit file="/base/base.html"/>
2 <%inherit file="/base/base.html"/>
3 <%def name="title()">
3 <%def name="title()">
4 ${_('Journal')}
4 ${_('Journal')}
5 %if c.site_name:
5 %if c.site_name:
6 &middot; ${c.site_name}
6 &middot; ${c.site_name}
7 %endif
7 %endif
8 </%def>
8 </%def>
9 <%def name="breadcrumbs()">
9 <%def name="breadcrumbs()">
10 <h5>
10 <h5>
11 <form id="filter_form">
11 <form id="filter_form">
12 <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...')}"/>
12 <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...')}"/>
13 <span class="tooltip" title="${h.tooltip(h.journal_filter_help())}">?</span>
13 <span class="tooltip" title="${h.tooltip(h.journal_filter_help())}">?</span>
14 <input type='submit' value="${_('filter')}" class="btn btn-small" style="padding:0px 2px 0px 2px;margin:0px"/>
14 <input type='submit' value="${_('filter')}" class="btn btn-small" style="padding:0px 2px 0px 2px;margin:0px"/>
15 ${_('journal')} - ${ungettext('%s entry', '%s entries', c.journal_pager.item_count) % (c.journal_pager.item_count)}
15 ${_('journal')} - ${ungettext('%s entry', '%s entries', c.journal_pager.item_count) % (c.journal_pager.item_count)}
16 </form>
16 </form>
17 ${h.end_form()}
17 ${h.end_form()}
18 </h5>
18 </h5>
19 </%def>
19 </%def>
20 <%def name="page_nav()">
20 <%def name="page_nav()">
21 ${self.menu('journal')}
21 ${self.menu('journal')}
22 </%def>
22 </%def>
23 <%def name="head_extra()">
23 <%def name="head_extra()">
24 <link href="${h.url('journal_atom', api_key=c.authuser.api_key)}" rel="alternate" title="${_('ATOM journal feed')}" type="application/atom+xml" />
24 <link href="${h.url('journal_atom', api_key=c.authuser.api_key)}" rel="alternate" title="${_('ATOM journal feed')}" type="application/atom+xml" />
25 <link href="${h.url('journal_rss', api_key=c.authuser.api_key)}" rel="alternate" title="${_('RSS journal feed')}" type="application/rss+xml" />
25 <link href="${h.url('journal_rss', api_key=c.authuser.api_key)}" rel="alternate" title="${_('RSS journal feed')}" type="application/rss+xml" />
26 </%def>
26 </%def>
27 <%def name="main()">
27 <%def name="main()">
28
28
29 <div class="box box-left">
29 <div class="box box-left">
30 <!-- box / title -->
30 <!-- box / title -->
31 <div class="title">
31 <div class="title">
32 ${self.breadcrumbs()}
32 ${self.breadcrumbs()}
33 <ul class="links icon-only-links">
33 <ul class="links icon-only-links">
34 <li>
34 <li>
35 <span><a id="refresh" href="${h.url('journal')}"><i class="icon-refresh"></i></a></span>
35 <span><a id="refresh" href="${h.url('journal')}"><i class="icon-refresh"></i></a></span>
36 </li>
36 </li>
37 <li>
37 <li>
38 <span><a href="${h.url('journal_atom', api_key=c.authuser.api_key)}"><i class="icon-rss-sign"></i></a></span>
38 <span><a href="${h.url('journal_atom', api_key=c.authuser.api_key)}"><i class="icon-rss-sign"></i></a></span>
39 </li>
39 </li>
40 </ul>
40 </ul>
41 </div>
41 </div>
42 <div id="journal">${c.journal_data}</div>
42 <div id="journal">${c.journal_data}</div>
43 </div>
43 </div>
44 <div class="box box-right">
44 <div class="box box-right">
45 <!-- box / title -->
45 <!-- box / title -->
46
46
47 <div class="title">
47 <div class="title">
48 <h5>
48 <h5>
49 <input class="q_filter_box" id="q_filter" size="15" type="text" name="filter" placeholder="${_('quick filter...')}" value="" style="display: none"/>
49 <input class="q_filter_box" id="q_filter" size="15" type="text" name="filter" placeholder="${_('quick filter...')}" value="" style="display: none"/>
50 <input class="q_filter_box" id="q_filter_watched" size="15" type="text" name="filter" placeholder="${_('quick filter...')}" value="" style="display: none"/>
50 <input class="q_filter_box" id="q_filter_watched" size="15" type="text" name="filter" placeholder="${_('quick filter...')}" value="" style="display: none"/>
51 </h5>
51 </h5>
52 <ul class="links nav nav-tabs">
52 <ul class="links nav nav-tabs">
53 <li class="active" id="show_watched_li">
53 <li class="active" id="show_watched_li">
54 <a id="show_watched" href="#watched"><i class="icon-eye-open"></i> ${_('Watched')}</a>
54 <a id="show_watched" href="#watched"><i class="icon-eye-open"></i> ${_('Watched')}</a>
55 </li>
55 </li>
56 <li id="show_my_li">
56 <li id="show_my_li">
57 <a id="show_my" href="#my"><i class="icon-archive"></i> ${_('My repos')}</a>
57 <a id="show_my" href="#my"><i class="icon-archive"></i> ${_('My repos')}</a>
58 </li>
58 </li>
59 </ul>
59 </ul>
60 </div>
60 </div>
61
61
62 <!-- end box / title -->
62 <!-- end box / title -->
63 <div id="my_container" style="display:none">
63 <div id="my_container" style="display:none">
64 <div class="table-grid table yui-skin-sam" id="repos_list_wrap"></div>
64 <div class="table-grid table yui-skin-sam" id="repos_list_wrap"></div>
65 <div id="user-paginator" style="padding: 0px 0px 0px 20px"></div>
65 <div id="user-paginator" style="padding: 0px 0px 0px 20px"></div>
66 </div>
66 </div>
67
67
68 <div id="watched_container">
68 <div id="watched_container">
69 <div class="table-grid table yui-skin-sam" id="watched_repos_list_wrap"></div>
69 <div class="table-grid table yui-skin-sam" id="watched_repos_list_wrap"></div>
70 <div id="watched-user-paginator" style="padding: 0px 0px 0px 20px"></div>
70 <div id="watched-user-paginator" style="padding: 0px 0px 0px 20px"></div>
71 </div>
71 </div>
72 </div>
72 </div>
73
73
74 <script type="text/javascript">
74 <script type="text/javascript">
75
75
76 $('#j_filter').click(function(){
76 $('#j_filter').click(function(){
77 var $jfilter = $('#j_filter');
77 var $jfilter = $('#j_filter');
78 if($jfilter.hasClass('initial')){
78 if($jfilter.hasClass('initial')){
79 $jfilter.val('');
79 $jfilter.val('');
80 }
80 }
81 });
81 });
82 var fix_j_filter_width = function(len){
82 var fix_j_filter_width = function(len){
83 $('#j_filter').css('width', Math.max(80, len*6.50)+'px');
83 $('#j_filter').css('width', Math.max(80, len*6.50)+'px');
84 };
84 };
85 $('#j_filter').keyup(function(){
85 $('#j_filter').keyup(function(){
86 fix_j_filter_width($('#j_filter').val().length);
86 fix_j_filter_width($('#j_filter').val().length);
87 });
87 });
88 $('#filter_form').submit(function(e){
88 $('#filter_form').submit(function(e){
89 e.preventDefault();
89 e.preventDefault();
90 var val = $('#j_filter').val();
90 var val = $('#j_filter').val();
91 window.location = "${url.current(filter='__FILTER__')}".replace('__FILTER__',val);
91 window.location = "${url.current(filter='__FILTER__')}".replace('__FILTER__',val);
92 });
92 });
93 fix_j_filter_width($('#j_filter').val().length);
93 fix_j_filter_width($('#j_filter').val().length);
94
94
95 $('#refresh').click(function(e){
95 $('#refresh').click(function(e){
96 asynchtml("${h.url.current(filter=c.search_term)}", $("#journal"), function(){
96 asynchtml("${h.url.current(filter=c.search_term)}", $("#journal"), function(){
97 show_more_event();
97 show_more_event();
98 tooltip_activate();
98 tooltip_activate();
99 show_changeset_tooltip();
99 show_changeset_tooltip();
100 });
100 });
101 e.preventDefault();
101 e.preventDefault();
102 });
102 });
103
103
104 var show_my = function(e){
104 var show_my = function(e){
105 $('#watched_container').hide();
105 $('#watched_container').hide();
106 $('#my_container').show();
106 $('#my_container').show();
107 $('#q_filter').show();
107 $('#q_filter').show();
108 $('#q_filter_watched').hide();
108 $('#q_filter_watched').hide();
109
109
110 $('#show_my_li').addClass('active');
110 $('#show_my_li').addClass('active');
111 $('#show_watched_li').removeClass('active');
111 $('#show_watched_li').removeClass('active');
112 if(!$('#show_my').hasClass('loaded')){
112 if(!$('#show_my').hasClass('loaded')){
113 table_renderer(${c.data |n});
113 table_renderer(${c.data |n});
114 $('#show_my').addClass('loaded');
114 $('#show_my').addClass('loaded');
115 }
115 }
116 };
116 };
117 $('#show_my').click(function(){
117 $('#show_my').click(function(){
118 show_my();
118 show_my();
119 });
119 });
120 var show_watched = function(){
120 var show_watched = function(){
121 $('#my_container').hide();
121 $('#my_container').hide();
122 $('#watched_container').show();
122 $('#watched_container').show();
123 $('#q_filter_watched').show();
123 $('#q_filter_watched').show();
124 $('#q_filter').hide();
124 $('#q_filter').hide();
125
125
126 $('#show_watched_li').addClass('active');
126 $('#show_watched_li').addClass('active');
127 $('#show_my_li').removeClass('active');
127 $('#show_my_li').removeClass('active');
128 if(!$('#show_watched').hasClass('loaded')){
128 if(!$('#show_watched').hasClass('loaded')){
129 watched_renderer(${c.watched_data |n});
129 watched_renderer(${c.watched_data |n});
130 $('#show_watched').addClass('loaded');
130 $('#show_watched').addClass('loaded');
131 }
131 }
132 };
132 };
133 $('#show_watched').click(function(){
133 $('#show_watched').click(function(){
134 show_watched();
134 show_watched();
135 });
135 });
136 //init watched
136 //init watched
137 show_watched();
137 show_watched();
138
138
139 var tabs = {
139 var tabs = {
140 'watched': show_watched,
140 'watched': show_watched,
141 'my': show_my,
141 'my': show_my
142 }
142 }
143 var url = location.href.split('#');
143 var url = location.href.split('#');
144 if (url[1]) {
144 if (url[1]) {
145 //We have a hash
145 //We have a hash
146 var tabHash = url[1];
146 var tabHash = url[1];
147 var func = tabs[tabHash]
147 var func = tabs[tabHash]
148 if (func){
148 if (func){
149 func();
149 func();
150 }
150 }
151 }
151 }
152 function watched_renderer(data){
152 function watched_renderer(data){
153 var myDataSource = new YAHOO.util.DataSource(data);
153 var myDataSource = new YAHOO.util.DataSource(data);
154 myDataSource.responseType = YAHOO.util.DataSource.TYPE_JSON;
154 myDataSource.responseType = YAHOO.util.DataSource.TYPE_JSON;
155
155
156 myDataSource.responseSchema = {
156 myDataSource.responseSchema = {
157 resultsList: "records",
157 resultsList: "records",
158 fields: [
158 fields: [
159 {key:"menu"},
159 {key:"menu"},
160 {key:"raw_name"},
160 {key:"raw_name"},
161 {key:"name"},
161 {key:"name"},
162 {key:"last_changeset"},
162 {key:"last_changeset"},
163 {key:"last_rev_raw"},
163 {key:"last_rev_raw"},
164 {key:"action"},
164 {key:"action"}
165 ]
165 ]
166 };
166 };
167 myDataSource.doBeforeCallback = function(req,raw,res,cb) {
167 myDataSource.doBeforeCallback = function(req,raw,res,cb) {
168 // This is the filter function
168 // This is the filter function
169 var data = res.results || [],
169 var data = res.results || [],
170 filtered = [],
170 filtered = [],
171 i,l;
171 i,l;
172
172
173 if (req) {
173 if (req) {
174 req = req.toLowerCase();
174 req = req.toLowerCase();
175 for (i = 0; i<data.length; i++) {
175 for (i = 0; i<data.length; i++) {
176 var pos = data[i].raw_name.toLowerCase().indexOf(req)
176 var pos = data[i].raw_name.toLowerCase().indexOf(req)
177 if (pos != -1) {
177 if (pos != -1) {
178 filtered.push(data[i]);
178 filtered.push(data[i]);
179 }
179 }
180 }
180 }
181 res.results = filtered;
181 res.results = filtered;
182 }
182 }
183 return res;
183 return res;
184 }
184 }
185 // main table sorting
185 // main table sorting
186 var myColumnDefs = [
186 var myColumnDefs = [
187 {key:"menu",label:"",sortable:false,className:"quick_repo_menu hidden"},
187 {key:"menu",label:"",sortable:false,className:"quick_repo_menu hidden"},
188 {key:"name",label:"${_('Name')}",sortable:true,
188 {key:"name",label:"${_('Name')}",sortable:true,
189 sortOptions: { sortFunction: nameSort }},
189 sortOptions: { sortFunction: nameSort }},
190 {key:"last_changeset",label:"${_('Tip')}",sortable:true,
190 {key:"last_changeset",label:"${_('Tip')}",sortable:true,
191 sortOptions: { sortFunction: revisionSort }},
191 sortOptions: { sortFunction: revisionSort }},
192 {key:"action",label:"${_('Action')}",sortable:false},
192 {key:"action",label:"${_('Action')}",sortable:false}
193 ];
193 ];
194
194
195 var myDataTable = new YAHOO.widget.DataTable("watched_repos_list_wrap", myColumnDefs, myDataSource,{
195 var myDataTable = new YAHOO.widget.DataTable("watched_repos_list_wrap", myColumnDefs, myDataSource,{
196 sortedBy:{key:"name",dir:"asc"},
196 sortedBy:{key:"name",dir:"asc"},
197 paginator: YUI_paginator(25, ['watched-user-paginator']),
197 paginator: YUI_paginator(25, ['watched-user-paginator']),
198
198
199 MSG_SORTASC:"${_('Click to sort ascending')}",
199 MSG_SORTASC:"${_('Click to sort ascending')}",
200 MSG_SORTDESC:"${_('Click to sort descending')}",
200 MSG_SORTDESC:"${_('Click to sort descending')}",
201 MSG_EMPTY:"${_('No records found.')}",
201 MSG_EMPTY:"${_('No records found.')}",
202 MSG_ERROR:"${_('Data error.')}",
202 MSG_ERROR:"${_('Data error.')}",
203 MSG_LOADING:"${_('Loading...')}",
203 MSG_LOADING:"${_('Loading...')}"
204 }
204 }
205 );
205 );
206 myDataTable.subscribe('postRenderEvent',function(oArgs) {
206 myDataTable.subscribe('postRenderEvent',function(oArgs) {
207 tooltip_activate();
207 tooltip_activate();
208 quick_repo_menu();
208 quick_repo_menu();
209 });
209 });
210
210
211 var filterTimeout = null;
211 var filterTimeout = null;
212
212
213 updateFilter = function () {
213 updateFilter = function () {
214 // Reset timeout
214 // Reset timeout
215 filterTimeout = null;
215 filterTimeout = null;
216
216
217 // Reset sort
217 // Reset sort
218 var state = myDataTable.getState();
218 var state = myDataTable.getState();
219 state.sortedBy = {key:'name', dir:YAHOO.widget.DataTable.CLASS_ASC};
219 state.sortedBy = {key:'name', dir:YAHOO.widget.DataTable.CLASS_ASC};
220
220
221 // Get filtered data
221 // Get filtered data
222 myDataSource.sendRequest(YUD.get('q_filter_watched').value,{
222 myDataSource.sendRequest(YUD.get('q_filter_watched').value,{
223 success : myDataTable.onDataReturnInitializeTable,
223 success : myDataTable.onDataReturnInitializeTable,
224 failure : myDataTable.onDataReturnInitializeTable,
224 failure : myDataTable.onDataReturnInitializeTable,
225 scope : myDataTable,
225 scope : myDataTable,
226 argument: state
226 argument: state
227 });
227 });
228
228
229 };
229 };
230 $('#q_filter_watched').click(function(){
230 $('#q_filter_watched').click(function(){
231 if(!$('#q_filter_watched').hasClass('loaded')) {
231 if(!$('#q_filter_watched').hasClass('loaded')) {
232 //TODO: load here full list later to do search within groups
232 //TODO: load here full list later to do search within groups
233 $('#q_filter_watched').css('loaded');
233 $('#q_filter_watched').css('loaded');
234 }
234 }
235 });
235 });
236
236
237 $('#q_filter_watched').keyup(function(){
237 $('#q_filter_watched').keyup(function(){
238 clearTimeout(filterTimeout);
238 clearTimeout(filterTimeout);
239 filterTimeout = setTimeout(updateFilter,600);
239 filterTimeout = setTimeout(updateFilter,600);
240 });
240 });
241 }
241 }
242
242
243 function table_renderer(data){
243 function table_renderer(data){
244 var myDataSource = new YAHOO.util.DataSource(data);
244 var myDataSource = new YAHOO.util.DataSource(data);
245 myDataSource.responseType = YAHOO.util.DataSource.TYPE_JSON;
245 myDataSource.responseType = YAHOO.util.DataSource.TYPE_JSON;
246
246
247 myDataSource.responseSchema = {
247 myDataSource.responseSchema = {
248 resultsList: "records",
248 resultsList: "records",
249 fields: [
249 fields: [
250 {key:"menu"},
250 {key:"menu"},
251 {key:"raw_name"},
251 {key:"raw_name"},
252 {key:"name"},
252 {key:"name"},
253 {key:"last_changeset"},
253 {key:"last_changeset"},
254 {key:"last_rev_raw"},
254 {key:"last_rev_raw"},
255 {key:"action"},
255 {key:"action"}
256 ]
256 ]
257 };
257 };
258 myDataSource.doBeforeCallback = function(req,raw,res,cb) {
258 myDataSource.doBeforeCallback = function(req,raw,res,cb) {
259 // This is the filter function
259 // This is the filter function
260 var data = res.results || [],
260 var data = res.results || [],
261 filtered = [],
261 filtered = [],
262 i,l;
262 i,l;
263
263
264 if (req) {
264 if (req) {
265 req = req.toLowerCase();
265 req = req.toLowerCase();
266 for (i = 0; i<data.length; i++) {
266 for (i = 0; i<data.length; i++) {
267 var pos = data[i].raw_name.toLowerCase().indexOf(req)
267 var pos = data[i].raw_name.toLowerCase().indexOf(req)
268 if (pos != -1) {
268 if (pos != -1) {
269 filtered.push(data[i]);
269 filtered.push(data[i]);
270 }
270 }
271 }
271 }
272 res.results = filtered;
272 res.results = filtered;
273 }
273 }
274 return res;
274 return res;
275 }
275 }
276 // main table sorting
276 // main table sorting
277 var myColumnDefs = [
277 var myColumnDefs = [
278 {key:"menu",label:"",sortable:false,className:"quick_repo_menu hidden"},
278 {key:"menu",label:"",sortable:false,className:"quick_repo_menu hidden"},
279 {key:"name",label:"${_('Name')}",sortable:true,
279 {key:"name",label:"${_('Name')}",sortable:true,
280 sortOptions: { sortFunction: nameSort }},
280 sortOptions: { sortFunction: nameSort }},
281 {key:"last_changeset",label:"${_('Tip')}",sortable:true,
281 {key:"last_changeset",label:"${_('Tip')}",sortable:true,
282 sortOptions: { sortFunction: revisionSort }},
282 sortOptions: { sortFunction: revisionSort }},
283 {key:"action",label:"${_('Action')}",sortable:false},
283 {key:"action",label:"${_('Action')}",sortable:false}
284 ];
284 ];
285
285
286 var myDataTable = new YAHOO.widget.DataTable("repos_list_wrap", myColumnDefs, myDataSource,{
286 var myDataTable = new YAHOO.widget.DataTable("repos_list_wrap", myColumnDefs, myDataSource,{
287 sortedBy:{key:"name",dir:"asc"},
287 sortedBy:{key:"name",dir:"asc"},
288 paginator: YUI_paginator(25, ['user-paginator']),
288 paginator: YUI_paginator(25, ['user-paginator']),
289
289
290 MSG_SORTASC:"${_('Click to sort ascending')}",
290 MSG_SORTASC:"${_('Click to sort ascending')}",
291 MSG_SORTDESC:"${_('Click to sort descending')}",
291 MSG_SORTDESC:"${_('Click to sort descending')}",
292 MSG_EMPTY:"${_('No records found.')}",
292 MSG_EMPTY:"${_('No records found.')}",
293 MSG_ERROR:"${_('Data error.')}",
293 MSG_ERROR:"${_('Data error.')}",
294 MSG_LOADING:"${_('Loading...')}",
294 MSG_LOADING:"${_('Loading...')}"
295 }
295 }
296 );
296 );
297 myDataTable.subscribe('postRenderEvent',function(oArgs) {
297 myDataTable.subscribe('postRenderEvent',function(oArgs) {
298 tooltip_activate();
298 tooltip_activate();
299 quick_repo_menu();
299 quick_repo_menu();
300 });
300 });
301
301
302 var filterTimeout = null;
302 var filterTimeout = null;
303
303
304 updateFilter = function () {
304 updateFilter = function () {
305 // Reset timeout
305 // Reset timeout
306 filterTimeout = null;
306 filterTimeout = null;
307
307
308 // Reset sort
308 // Reset sort
309 var state = myDataTable.getState();
309 var state = myDataTable.getState();
310 state.sortedBy = {key:'name', dir:YAHOO.widget.DataTable.CLASS_ASC};
310 state.sortedBy = {key:'name', dir:YAHOO.widget.DataTable.CLASS_ASC};
311
311
312 // Get filtered data
312 // Get filtered data
313 myDataSource.sendRequest(YUD.get('q_filter').value,{
313 myDataSource.sendRequest(YUD.get('q_filter').value,{
314 success : myDataTable.onDataReturnInitializeTable,
314 success : myDataTable.onDataReturnInitializeTable,
315 failure : myDataTable.onDataReturnInitializeTable,
315 failure : myDataTable.onDataReturnInitializeTable,
316 scope : myDataTable,
316 scope : myDataTable,
317 argument: state
317 argument: state
318 });
318 });
319
319
320 };
320 };
321 $('#q_filter').click(function(){
321 $('#q_filter').click(function(){
322 if(!$('#q_filter').hasClass('loaded')){
322 if(!$('#q_filter').hasClass('loaded')){
323 //TODO: load here full list later to do search within groups
323 //TODO: load here full list later to do search within groups
324 $('#q_filter').addClass('loaded');
324 $('#q_filter').addClass('loaded');
325 }
325 }
326 });
326 });
327
327
328 $('#q_filter').keyup(function(){
328 $('#q_filter').keyup(function(){
329 clearTimeout(filterTimeout);
329 clearTimeout(filterTimeout);
330 filterTimeout = setTimeout(updateFilter,600);
330 filterTimeout = setTimeout(updateFilter,600);
331 });
331 });
332
332
333 if($('#q_filter').val()) {
333 if($('#q_filter').val()) {
334 updateFilter();
334 updateFilter();
335 }
335 }
336 }
336 }
337
337
338 </script>
338 </script>
339 </%def>
339 </%def>
@@ -1,88 +1,88 b''
1 ## -*- coding: utf-8 -*-
1 ## -*- coding: utf-8 -*-
2 <%inherit file="base/root.html"/>
2 <%inherit file="base/root.html"/>
3
3
4 <%def name="title()">
4 <%def name="title()">
5 ${_('Password Reset')}
5 ${_('Password Reset')}
6 %if c.site_name:
6 %if c.site_name:
7 &middot; ${c.site_name}
7 &middot; ${c.site_name}
8 %endif
8 %endif
9 </%def>
9 </%def>
10
10
11
11
12 <div id="header">
12 <div id="header">
13 <div id="header-inner" class="title">
13 <div id="header-inner" class="title">
14 <div id="logo">
14 <div id="logo">
15 <a href="${h.url('home')}" style="display: block;">
15 <a href="${h.url('home')}" style="display: block;">
16 <div class="header">
16 <div class="header">
17 <img src="${h.url('/images/kallithea-logo.svg')}" onerror="this.src='${h.url('/images/kallithea-logo.png')}'" alt="Kallithea"/>
17 <img src="${h.url('/images/kallithea-logo.svg')}" onerror="this.src='${h.url('/images/kallithea-logo.png')}'" alt="Kallithea"/>
18 </div>
18 </div>
19 %if c.site_name:
19 %if c.site_name:
20 <div class="branding">${c.site_name}</div>
20 <div class="branding">${c.site_name}</div>
21 %endif
21 %endif
22 </a>
22 </a>
23 </div>
23 </div>
24 </div>
24 </div>
25 </div>
25 </div>
26
26
27 <div id="register">
27 <div id="register">
28 <%include file="/base/flash_msg.html"/>
28 <%include file="/base/flash_msg.html"/>
29 <div class="title withlogo">
29 <div class="title withlogo">
30 %if c.site_name:
30 %if c.site_name:
31 <h5>${_('Reset your Password to %s') % c.site_name}</h5>
31 <h5>${_('Reset your Password to %s') % c.site_name}</h5>
32 %else:
32 %else:
33 <h5>${_('Reset your Password')}</h5>
33 <h5>${_('Reset your Password')}</h5>
34 %endif
34 %endif
35 </div>
35 </div>
36 <div class="inner">
36 <div class="inner">
37 ${h.form(url('password_reset'))}
37 ${h.form(url('password_reset'))}
38 <div class="form">
38 <div class="form">
39 <!-- fields -->
39 <!-- fields -->
40 <div class="fields">
40 <div class="fields">
41
41
42 <div class="field">
42 <div class="field">
43 <div class="label">
43 <div class="label">
44 <label for="email">${_('Email Address')}:</label>
44 <label for="email">${_('Email Address')}:</label>
45 </div>
45 </div>
46 <div class="input">
46 <div class="input">
47 ${h.text('email')}
47 ${h.text('email')}
48 </div>
48 </div>
49 </div>
49 </div>
50
50
51 %if c.captcha_active:
51 %if c.captcha_active:
52 <div class="field">
52 <div class="field">
53 <div class="label">
53 <div class="label">
54 <label for="email">${_('Captcha')}:</label>
54 <label for="email">${_('Captcha')}:</label>
55 </div>
55 </div>
56 <div class="input">
56 <div class="input">
57 ${h.hidden('recaptcha_field')}
57 ${h.hidden('recaptcha_field')}
58 <div id="recaptcha"></div>
58 <div id="recaptcha"></div>
59 </div>
59 </div>
60 </div>
60 </div>
61 %endif
61 %endif
62
62
63 <div class="buttons">
63 <div class="buttons">
64 <div class="nohighlight">
64 <div class="nohighlight">
65 ${h.submit('send',_('Send password reset email'),class_="btn")}
65 ${h.submit('send',_('Send password reset email'),class_="btn")}
66 <div class="activation_msg">${_('Password reset link will be send to matching email address')}</div>
66 <div class="activation_msg">${_('Password reset link will be send to matching email address')}</div>
67 </div>
67 </div>
68 </div>
68 </div>
69 </div>
69 </div>
70 </div>
70 </div>
71 ${h.end_form()}
71 ${h.end_form()}
72 %if c.captcha_active:
72 %if c.captcha_active:
73 <script type="text/javascript" src="https://www.google.com/recaptcha/api/js/recaptcha_ajax.js"></script>
73 <script type="text/javascript" src="https://www.google.com/recaptcha/api/js/recaptcha_ajax.js"></script>
74 %endif
74 %endif
75 <script type="text/javascript">
75 <script type="text/javascript">
76 $(document).ready(function(){
76 $(document).ready(function(){
77 $('#email').focus();
77 $('#email').focus();
78 %if c.captcha_active:
78 %if c.captcha_active:
79 Recaptcha.create("${c.captcha_public_key}", "recaptcha",
79 Recaptcha.create("${c.captcha_public_key}", "recaptcha",
80 {
80 {
81 theme: "white",
81 theme: "white"
82 }
82 }
83 );
83 );
84 %endif
84 %endif
85 });
85 });
86 </script>
86 </script>
87 </div>
87 </div>
88 </div>
88 </div>
@@ -1,260 +1,260 b''
1 <%inherit file="/base/base.html"/>
1 <%inherit file="/base/base.html"/>
2
2
3 <%def name="title()">
3 <%def name="title()">
4 ${c.repo_name} ${_('New pull request')}
4 ${c.repo_name} ${_('New pull request')}
5 </%def>
5 </%def>
6
6
7 <%def name="breadcrumbs_links()">
7 <%def name="breadcrumbs_links()">
8 ${_('New pull request')}
8 ${_('New pull request')}
9 </%def>
9 </%def>
10
10
11 <%def name="page_nav()">
11 <%def name="page_nav()">
12 ${self.menu('repositories')}
12 ${self.menu('repositories')}
13 </%def>
13 </%def>
14
14
15 <%def name="main()">
15 <%def name="main()">
16 ${self.repo_context_bar('showpullrequest')}
16 ${self.repo_context_bar('showpullrequest')}
17 <div class="box">
17 <div class="box">
18 <!-- box / title -->
18 <!-- box / title -->
19 <div class="title">
19 <div class="title">
20 ${self.breadcrumbs()}
20 ${self.breadcrumbs()}
21 </div>
21 </div>
22
22
23 ${h.form(url('pullrequest', repo_name=c.repo_name), method='post', id='pull_request_form')}
23 ${h.form(url('pullrequest', repo_name=c.repo_name), method='post', id='pull_request_form')}
24 <div class="form">
24 <div class="form">
25 <!-- fields -->
25 <!-- fields -->
26
26
27 <div class="fields" style="float:left;width:50%;padding-right:30px;">
27 <div class="fields" style="float:left;width:50%;padding-right:30px;">
28
28
29 <div class="field">
29 <div class="field">
30 <div class="label">
30 <div class="label">
31 <label for="pullrequest_title">${_('Title')}:</label>
31 <label for="pullrequest_title">${_('Title')}:</label>
32 </div>
32 </div>
33 <div class="input">
33 <div class="input">
34 ${h.text('pullrequest_title',class_="large",placeholder=_('Summarize the changes - or leave empty'))}
34 ${h.text('pullrequest_title',class_="large",placeholder=_('Summarize the changes - or leave empty'))}
35 </div>
35 </div>
36 </div>
36 </div>
37
37
38 <div class="field">
38 <div class="field">
39 <div class="label label-textarea">
39 <div class="label label-textarea">
40 <label for="pullrequest_desc">${_('Description')}:</label>
40 <label for="pullrequest_desc">${_('Description')}:</label>
41 </div>
41 </div>
42 <div class="textarea text-area editor">
42 <div class="textarea text-area editor">
43 ${h.textarea('pullrequest_desc',size=30,placeholder=_('Write a short description on this pull request'))}
43 ${h.textarea('pullrequest_desc',size=30,placeholder=_('Write a short description on this pull request'))}
44 </div>
44 </div>
45 </div>
45 </div>
46
46
47 <div class="field">
47 <div class="field">
48 <div class="label label-textarea">
48 <div class="label label-textarea">
49 <label for="pullrequest_desc">${_('Changeset flow')}:</label>
49 <label for="pullrequest_desc">${_('Changeset flow')}:</label>
50 </div>
50 </div>
51 <div class="input">
51 <div class="input">
52 ##ORG
52 ##ORG
53 <div>
53 <div>
54 <div>
54 <div>
55 <div style="padding:5px 3px 3px 3px;">
55 <div style="padding:5px 3px 3px 3px;">
56 <b>${_('Origin repository')}:</b> <span id="org_repo_desc">${c.db_repo.description.split('\n')[0]}</span>
56 <b>${_('Origin repository')}:</b> <span id="org_repo_desc">${c.db_repo.description.split('\n')[0]}</span>
57 </div>
57 </div>
58 <div>
58 <div>
59 ${h.select('org_repo','',c.cs_repos,class_='refs')}:${h.select('org_ref',c.default_cs_ref,c.cs_refs,class_='refs')}
59 ${h.select('org_repo','',c.cs_repos,class_='refs')}:${h.select('org_ref',c.default_cs_ref,c.cs_refs,class_='refs')}
60 </div>
60 </div>
61 <div style="padding:5px 3px 3px 3px;">
61 <div style="padding:5px 3px 3px 3px;">
62 <b>${_('Revision')}:</b> <span id="org_rev_span">-</span>
62 <b>${_('Revision')}:</b> <span id="org_rev_span">-</span>
63 </div>
63 </div>
64 </div>
64 </div>
65 </div>
65 </div>
66
66
67 ##OTHER, most Probably the PARENT OF THIS FORK
67 ##OTHER, most Probably the PARENT OF THIS FORK
68 <div style="border-top: 1px solid #EEE; margin: 5px 0px 0px 0px">
68 <div style="border-top: 1px solid #EEE; margin: 5px 0px 0px 0px">
69 <div>
69 <div>
70 ## filled with JS
70 ## filled with JS
71 <div style="padding:5px 3px 3px 3px;">
71 <div style="padding:5px 3px 3px 3px;">
72 <b>${_('Destination repository')}:</b> <span id="other_repo_desc">${c.a_repo.description.split('\n')[0]}</span>
72 <b>${_('Destination repository')}:</b> <span id="other_repo_desc">${c.a_repo.description.split('\n')[0]}</span>
73 </div>
73 </div>
74 <div>
74 <div>
75 ${h.select('other_repo',c.a_repo.repo_name,c.a_repos,class_='refs')}:${h.select('other_ref',c.default_a_ref,c.a_refs,class_='refs')}
75 ${h.select('other_repo',c.a_repo.repo_name,c.a_repos,class_='refs')}:${h.select('other_ref',c.default_a_ref,c.a_refs,class_='refs')}
76 </div>
76 </div>
77 <div style="padding:5px 3px 3px 3px;">
77 <div style="padding:5px 3px 3px 3px;">
78 <b>${_('Revision')}:</b> <span id="other_rev_span">-</span>
78 <b>${_('Revision')}:</b> <span id="other_rev_span">-</span>
79 </div>
79 </div>
80 </div>
80 </div>
81 </div>
81 </div>
82 <div style="clear:both"></div>
82 <div style="clear:both"></div>
83 </div>
83 </div>
84 </div>
84 </div>
85
85
86 <div class="field">
86 <div class="field">
87 <div class="buttons">
87 <div class="buttons">
88 ${h.submit('save',_('Create Pull Request'),class_="btn")}
88 ${h.submit('save',_('Create Pull Request'),class_="btn")}
89 ${h.reset('reset',_('Reset'),class_="btn")}
89 ${h.reset('reset',_('Reset'),class_="btn")}
90 </div>
90 </div>
91 </div>
91 </div>
92
92
93 </div>
93 </div>
94
94
95 ## Reviewers
95 ## Reviewers
96 <div style="float:left; border-left:1px dashed #eee">
96 <div style="float:left; border-left:1px dashed #eee">
97 <div class="pr-details-title">${_('Pull request reviewers')}</div>
97 <div class="pr-details-title">${_('Pull request reviewers')}</div>
98 <div id="reviewers" style="padding:0px 0px 0px 15px">
98 <div id="reviewers" style="padding:0px 0px 0px 15px">
99 ## members goes here !
99 ## members goes here !
100 <div>
100 <div>
101 <ul id="review_members" class="group_members">
101 <ul id="review_members" class="group_members">
102 %for member in [c.a_repo.user]:
102 %for member in [c.a_repo.user]:
103 <li id="reviewer_${member.user_id}">
103 <li id="reviewer_${member.user_id}">
104 <div class="reviewers_member">
104 <div class="reviewers_member">
105 <div class="gravatar"><img alt="gravatar" src="${h.gravatar_url(member.email, 14)}"/> </div>
105 <div class="gravatar"><img alt="gravatar" src="${h.gravatar_url(member.email, 14)}"/> </div>
106 <div style="float:left">${member.firstname} ${member.lastname} (${_('owner')})</div>
106 <div style="float:left">${member.firstname} ${member.lastname} (${_('owner')})</div>
107 <input type="hidden" value="${member.user_id}" name="review_members" />
107 <input type="hidden" value="${member.user_id}" name="review_members" />
108 <span class="action_button" style="padding: 3px" onclick="removeReviewMember(${member.user_id})" title="${_('Remove reviewer')}>
108 <span class="action_button" style="padding: 3px" onclick="removeReviewMember(${member.user_id})" title="${_('Remove reviewer')}>
109 <i class="icon-remove-sign" style="color: #FF4444;"></i>
109 <i class="icon-remove-sign" style="color: #FF4444;"></i>
110 </span>
110 </span>
111 </div>
111 </div>
112 </li>
112 </li>
113 %endfor
113 %endfor
114 </ul>
114 </ul>
115 </div>
115 </div>
116
116
117 <div class='ac'>
117 <div class='ac'>
118 <div class="reviewer_ac">
118 <div class="reviewer_ac">
119 ${h.text('user', class_='yui-ac-input',placeholder=_('Type name of reviewer to add'))}
119 ${h.text('user', class_='yui-ac-input',placeholder=_('Type name of reviewer to add'))}
120 <div id="reviewers_container"></div>
120 <div id="reviewers_container"></div>
121 </div>
121 </div>
122 </div>
122 </div>
123 </div>
123 </div>
124 </div>
124 </div>
125
125
126 <div style="clear:both;padding: 0 0 30px 0;"></div>
126 <div style="clear:both;padding: 0 0 30px 0;"></div>
127
127
128 <h4>${_('Changesets')}</h4>
128 <h4>${_('Changesets')}</h4>
129 <div style="float:left;padding:0px 30px 30px 30px">
129 <div style="float:left;padding:0px 30px 30px 30px">
130 ## overview pulled by ajax
130 ## overview pulled by ajax
131 <div style="float:left" id="pull_request_overview"></div>
131 <div style="float:left" id="pull_request_overview"></div>
132 </div>
132 </div>
133 <div style="clear:both;"></div>
133 <div style="clear:both;"></div>
134
134
135 </div>
135 </div>
136
136
137 ${h.end_form()}
137 ${h.end_form()}
138
138
139 </div>
139 </div>
140
140
141 <script type="text/javascript" src="${h.url('/js/graph.js')}"></script>
141 <script type="text/javascript" src="${h.url('/js/graph.js')}"></script>
142 <script type="text/javascript">
142 <script type="text/javascript">
143 var _USERS_AC_DATA = ${c.users_array|n};
143 var _USERS_AC_DATA = ${c.users_array|n};
144 var _GROUPS_AC_DATA = ${c.user_groups_array|n};
144 var _GROUPS_AC_DATA = ${c.user_groups_array|n};
145 PullRequestAutoComplete('user', 'reviewers_container', _USERS_AC_DATA, _GROUPS_AC_DATA);
145 PullRequestAutoComplete('user', 'reviewers_container', _USERS_AC_DATA, _GROUPS_AC_DATA);
146
146
147 pyroutes.register('pullrequest_repo_info', "${url('pullrequest_repo_info',repo_name='%(repo_name)s')}", ['repo_name']);
147 pyroutes.register('pullrequest_repo_info', "${url('pullrequest_repo_info',repo_name='%(repo_name)s')}", ['repo_name']);
148
148
149 var otherrepoChanged = function(){
149 var otherrepoChanged = function(){
150 var repo_name = $('#other_repo').val();
150 var repo_name = $('#other_repo').val();
151 ajaxGET(pyroutes.url('pullrequest_repo_info', {"repo_name": repo_name}),
151 ajaxGET(pyroutes.url('pullrequest_repo_info', {"repo_name": repo_name}),
152 function(o){
152 function(o){
153 var data = JSON.parse(o.responseText);
153 var data = JSON.parse(o.responseText);
154 $('#other_repo_desc').html(data.description);
154 $('#other_repo_desc').html(data.description);
155
155
156 // replace options of other_ref with the ones for the current other_repo
156 // replace options of other_ref with the ones for the current other_repo
157 var $other_ref = $('#other_ref');
157 var $other_ref = $('#other_ref');
158 $other_ref.empty();
158 $other_ref.empty();
159 for(var i = 0; i < data.refs.length; i++)
159 for(var i = 0; i < data.refs.length; i++)
160 {
160 {
161 var $optgroup = $('<optgroup/>').attr('label', data.refs[i][1]);
161 var $optgroup = $('<optgroup/>').attr('label', data.refs[i][1]);
162 var options = data.refs[i][0];
162 var options = data.refs[i][0];
163 var length = options.length;
163 var length = options.length;
164 for(var j = 0; j < length; j++)
164 for(var j = 0; j < length; j++)
165 {
165 {
166 $optgroup.append($('<option/>').text(options[j][1]).val(options[j][0]));
166 $optgroup.append($('<option/>').text(options[j][1]).val(options[j][0]));
167 }
167 }
168 $other_ref.append($optgroup);
168 $other_ref.append($optgroup);
169 }
169 }
170 $other_ref.val(data.selected_ref);
170 $other_ref.val(data.selected_ref);
171
171
172 // reset && add the reviewer based on selected repo
172 // reset && add the reviewer based on selected repo
173 YUD.get('review_members').innerHTML = '';
173 YUD.get('review_members').innerHTML = '';
174 addReviewMember(data.user.user_id, data.user.firstname,
174 addReviewMember(data.user.user_id, data.user.firstname,
175 data.user.lastname, data.user.username,
175 data.user.lastname, data.user.username,
176 data.user.gravatar_link);
176 data.user.gravatar_link);
177
177
178 // re-populate the select2 thingie
178 // re-populate the select2 thingie
179 $("#other_ref").select2({
179 $("#other_ref").select2({
180 dropdownAutoWidth: true,
180 dropdownAutoWidth: true
181 });
181 });
182
182
183 loadPreview();
183 loadPreview();
184 });
184 });
185 };
185 };
186
186
187 var loadPreview = function(){
187 var loadPreview = function(){
188 //url template
188 //url template
189 var url = "${h.url('compare_url',
189 var url = "${h.url('compare_url',
190 repo_name='__other_repo__',
190 repo_name='__other_repo__',
191 org_ref_type='rev',
191 org_ref_type='rev',
192 org_ref_name='__other_ref_name__',
192 org_ref_name='__other_ref_name__',
193 other_repo='__org_repo__',
193 other_repo='__org_repo__',
194 other_ref_type='rev',
194 other_ref_type='rev',
195 other_ref_name='__org_ref_name__',
195 other_ref_name='__org_ref_name__',
196 as_form=True,
196 as_form=True,
197 merge=True,
197 merge=True,
198 )}";
198 )}";
199 var org_repo = YUQ('#pull_request_form #org_repo')[0].value;
199 var org_repo = YUQ('#pull_request_form #org_repo')[0].value;
200 var org_ref = YUQ('#pull_request_form #org_ref')[0].value.split(':');
200 var org_ref = YUQ('#pull_request_form #org_ref')[0].value.split(':');
201 ## TODO: make nice link like link_to_ref() do
201 ## TODO: make nice link like link_to_ref() do
202 YUD.get('org_rev_span').innerHTML = org_ref[2].substr(0,12);
202 YUD.get('org_rev_span').innerHTML = org_ref[2].substr(0,12);
203
203
204 var other_repo = YUQ('#pull_request_form #other_repo')[0].value;
204 var other_repo = YUQ('#pull_request_form #other_repo')[0].value;
205 var other_ref = YUQ('#pull_request_form #other_ref')[0].value.split(':');
205 var other_ref = YUQ('#pull_request_form #other_ref')[0].value.split(':');
206 YUD.get('other_rev_span').innerHTML = other_ref[2].substr(0,12);
206 YUD.get('other_rev_span').innerHTML = other_ref[2].substr(0,12);
207
207
208 var select_refs = YUQ('#pull_request_form select.refs')
208 var select_refs = YUQ('#pull_request_form select.refs')
209 var rev_data = {
209 var rev_data = {
210 '__org_repo__': org_repo,
210 '__org_repo__': org_repo,
211 '__org_ref_name__': org_ref[2],
211 '__org_ref_name__': org_ref[2],
212 '__other_repo__': other_repo,
212 '__other_repo__': other_repo,
213 '__other_ref_name__': other_ref[2],
213 '__other_ref_name__': other_ref[2]
214 }; // gather the org/other ref and repo here
214 }; // gather the org/other ref and repo here
215
215
216 for (k in rev_data){
216 for (k in rev_data){
217 url = url.replace(k,rev_data[k]);
217 url = url.replace(k,rev_data[k]);
218 }
218 }
219
219
220 asynchtml(url, $('#pull_request_overview'), function(o){
220 asynchtml(url, $('#pull_request_overview'), function(o){
221 var jsdata = eval('('+YUD.get('jsdata').innerHTML+')'); // TODO: just get json
221 var jsdata = eval('('+YUD.get('jsdata').innerHTML+')'); // TODO: just get json
222 var r = new BranchRenderer('graph_canvas', 'graph_content_pr');
222 var r = new BranchRenderer('graph_canvas', 'graph_content_pr');
223 r.render(jsdata,100);
223 r.render(jsdata,100);
224 });
224 });
225 }
225 }
226
226
227 $(document).ready(function(){
227 $(document).ready(function(){
228 $("#org_repo").select2({
228 $("#org_repo").select2({
229 dropdownAutoWidth: true,
229 dropdownAutoWidth: true
230 });
230 });
231 ## (org_repo can't change)
231 ## (org_repo can't change)
232
232
233 $("#org_ref").select2({
233 $("#org_ref").select2({
234 dropdownAutoWidth: true,
234 dropdownAutoWidth: true
235 });
235 });
236 $("#org_ref").on("change", function(e){
236 $("#org_ref").on("change", function(e){
237 loadPreview();
237 loadPreview();
238 });
238 });
239
239
240 $("#other_repo").select2({
240 $("#other_repo").select2({
241 dropdownAutoWidth: true,
241 dropdownAutoWidth: true
242 });
242 });
243 $("#other_repo").on("change", function(e){
243 $("#other_repo").on("change", function(e){
244 otherrepoChanged();
244 otherrepoChanged();
245 });
245 });
246
246
247 $("#other_ref").select2({
247 $("#other_ref").select2({
248 dropdownAutoWidth: true,
248 dropdownAutoWidth: true
249 });
249 });
250 $("#other_ref").on("change", function(e){
250 $("#other_ref").on("change", function(e){
251 loadPreview();
251 loadPreview();
252 });
252 });
253
253
254 //lazy load overview after 0.5s
254 //lazy load overview after 0.5s
255 setTimeout(loadPreview, 500);
255 setTimeout(loadPreview, 500);
256 });
256 });
257
257
258 </script>
258 </script>
259
259
260 </%def>
260 </%def>
@@ -1,136 +1,136 b''
1 ## -*- coding: utf-8 -*-
1 ## -*- coding: utf-8 -*-
2 <%inherit file="base/root.html"/>
2 <%inherit file="base/root.html"/>
3
3
4 <%def name="title()">
4 <%def name="title()">
5 ${_('Sign Up')}
5 ${_('Sign Up')}
6 %if c.site_name:
6 %if c.site_name:
7 &middot; ${c.site_name}
7 &middot; ${c.site_name}
8 %endif
8 %endif
9 </%def>
9 </%def>
10 <div id="header">
10 <div id="header">
11 <div id="header-inner" class="title">
11 <div id="header-inner" class="title">
12 <div id="logo">
12 <div id="logo">
13 <a href="${h.url('home')}" style="display: block;">
13 <a href="${h.url('home')}" style="display: block;">
14 <div class="header">
14 <div class="header">
15 <img src="${h.url('/images/kallithea-logo.svg')}" onerror="this.src='${h.url('/images/kallithea-logo.png')}'" alt="Kallithea"/>
15 <img src="${h.url('/images/kallithea-logo.svg')}" onerror="this.src='${h.url('/images/kallithea-logo.png')}'" alt="Kallithea"/>
16 </div>
16 </div>
17 %if c.site_name:
17 %if c.site_name:
18 <div class="branding">${c.site_name}</div>
18 <div class="branding">${c.site_name}</div>
19 %endif
19 %endif
20 </a>
20 </a>
21 </div>
21 </div>
22 </div>
22 </div>
23 </div>
23 </div>
24
24
25
25
26 <div id="register">
26 <div id="register">
27 <%include file="/base/flash_msg.html"/>
27 <%include file="/base/flash_msg.html"/>
28 <div class="title withlogo">
28 <div class="title withlogo">
29 %if c.site_name:
29 %if c.site_name:
30 <h5>${_('Sign Up to %s') % c.site_name}</h5>
30 <h5>${_('Sign Up to %s') % c.site_name}</h5>
31 %else:
31 %else:
32 <h5>${_('Sign Up')}</h5>
32 <h5>${_('Sign Up')}</h5>
33 %endif
33 %endif
34 </div>
34 </div>
35 <div class="inner">
35 <div class="inner">
36 ${h.form(url('register'))}
36 ${h.form(url('register'))}
37 <div class="form">
37 <div class="form">
38 <!-- fields -->
38 <!-- fields -->
39 <div class="fields">
39 <div class="fields">
40 <div class="field">
40 <div class="field">
41 <div class="label">
41 <div class="label">
42 <label for="username">${_('Username')}:</label>
42 <label for="username">${_('Username')}:</label>
43 </div>
43 </div>
44 <div class="input">
44 <div class="input">
45 ${h.text('username',class_="medium")}
45 ${h.text('username',class_="medium")}
46 </div>
46 </div>
47 </div>
47 </div>
48
48
49 <div class="field">
49 <div class="field">
50 <div class="label">
50 <div class="label">
51 <label for="password">${_('Password')}:</label>
51 <label for="password">${_('Password')}:</label>
52 </div>
52 </div>
53 <div class="input">
53 <div class="input">
54 ${h.password('password',class_="medium",autocomplete="off")}
54 ${h.password('password',class_="medium",autocomplete="off")}
55 </div>
55 </div>
56 </div>
56 </div>
57
57
58 <div class="field">
58 <div class="field">
59 <div class="label">
59 <div class="label">
60 <label for="password">${_('Re-enter password')}:</label>
60 <label for="password">${_('Re-enter password')}:</label>
61 </div>
61 </div>
62 <div class="input">
62 <div class="input">
63 ${h.password('password_confirmation',class_="medium",autocomplete="off")}
63 ${h.password('password_confirmation',class_="medium",autocomplete="off")}
64 </div>
64 </div>
65 </div>
65 </div>
66
66
67 <div class="field">
67 <div class="field">
68 <div class="label">
68 <div class="label">
69 <label for="firstname">${_('First Name')}:</label>
69 <label for="firstname">${_('First Name')}:</label>
70 </div>
70 </div>
71 <div class="input">
71 <div class="input">
72 ${h.text('firstname',class_="medium")}
72 ${h.text('firstname',class_="medium")}
73 </div>
73 </div>
74 </div>
74 </div>
75
75
76 <div class="field">
76 <div class="field">
77 <div class="label">
77 <div class="label">
78 <label for="lastname">${_('Last Name')}:</label>
78 <label for="lastname">${_('Last Name')}:</label>
79 </div>
79 </div>
80 <div class="input">
80 <div class="input">
81 ${h.text('lastname',class_="medium")}
81 ${h.text('lastname',class_="medium")}
82 </div>
82 </div>
83 </div>
83 </div>
84
84
85 <div class="field">
85 <div class="field">
86 <div class="label">
86 <div class="label">
87 <label for="email">${_('Email')}:</label>
87 <label for="email">${_('Email')}:</label>
88 </div>
88 </div>
89 <div class="input">
89 <div class="input">
90 ${h.text('email',class_="medium")}
90 ${h.text('email',class_="medium")}
91 </div>
91 </div>
92 </div>
92 </div>
93
93
94 %if c.captcha_active:
94 %if c.captcha_active:
95 <div class="field">
95 <div class="field">
96 <div class="label">
96 <div class="label">
97 <label for="email">${_('Captcha')}:</label>
97 <label for="email">${_('Captcha')}:</label>
98 </div>
98 </div>
99 <div class="input">
99 <div class="input">
100 ${h.hidden('recaptcha_field')}
100 ${h.hidden('recaptcha_field')}
101 <div id="recaptcha"></div>
101 <div id="recaptcha"></div>
102 </div>
102 </div>
103 </div>
103 </div>
104 %endif
104 %endif
105
105
106 <div class="buttons">
106 <div class="buttons">
107 <div class="nohighlight">
107 <div class="nohighlight">
108 ${h.submit('sign_up',_('Sign Up'),class_="btn")}
108 ${h.submit('sign_up',_('Sign Up'),class_="btn")}
109 %if c.auto_active:
109 %if c.auto_active:
110 <div class="activation_msg">${_('Your account will be activated right after registration')}</div>
110 <div class="activation_msg">${_('Your account will be activated right after registration')}</div>
111 %else:
111 %else:
112 <div class="activation_msg">${_('Your account must wait for activation by administrator')}</div>
112 <div class="activation_msg">${_('Your account must wait for activation by administrator')}</div>
113 %endif
113 %endif
114 </div>
114 </div>
115 </div>
115 </div>
116 </div>
116 </div>
117 </div>
117 </div>
118 ${h.end_form()}
118 ${h.end_form()}
119 %if c.captcha_active:
119 %if c.captcha_active:
120 <script type="text/javascript" src="https://www.google.com/recaptcha/api/js/recaptcha_ajax.js"></script>
120 <script type="text/javascript" src="https://www.google.com/recaptcha/api/js/recaptcha_ajax.js"></script>
121 %endif
121 %endif
122 <script type="text/javascript">
122 <script type="text/javascript">
123 $(document).ready(function(){
123 $(document).ready(function(){
124 $('#username').focus();
124 $('#username').focus();
125
125
126 %if c.captcha_active:
126 %if c.captcha_active:
127 Recaptcha.create("${c.captcha_public_key}", "recaptcha",
127 Recaptcha.create("${c.captcha_public_key}", "recaptcha",
128 {
128 {
129 theme: "white",
129 theme: "white"
130 }
130 }
131 );
131 );
132 %endif
132 %endif
133 });
133 });
134 </script>
134 </script>
135 </div>
135 </div>
136 </div>
136 </div>
@@ -1,92 +1,92 b''
1 ## -*- coding: utf-8 -*-
1 ## -*- coding: utf-8 -*-
2 <%inherit file="/base/base.html"/>
2 <%inherit file="/base/base.html"/>
3
3
4 <%def name="title()">
4 <%def name="title()">
5 %if c.repo_name:
5 %if c.repo_name:
6 ${_('%s Search') % c.repo_name}
6 ${_('%s Search') % c.repo_name}
7 %else:
7 %else:
8 ${_('Search in all repositories')}
8 ${_('Search in all repositories')}
9 %endif
9 %endif
10 %if c.site_name:
10 %if c.site_name:
11 &middot; ${c.site_name}
11 &middot; ${c.site_name}
12 %endif
12 %endif
13 </%def>
13 </%def>
14
14
15 <%def name="breadcrumbs_links()">
15 <%def name="breadcrumbs_links()">
16 %if c.repo_name:
16 %if c.repo_name:
17 ${_('Search')}
17 ${_('Search')}
18 %else:
18 %else:
19 ${_('Search in all repositories')}
19 ${_('Search in all repositories')}
20 %endif
20 %endif
21 %if c.cur_query:
21 %if c.cur_query:
22 &raquo;
22 &raquo;
23 ${c.cur_query}
23 ${c.cur_query}
24 %endif
24 %endif
25 </%def>
25 </%def>
26
26
27 <%def name="page_nav()">
27 <%def name="page_nav()">
28 %if c.repo_name:
28 %if c.repo_name:
29 ${self.menu('repositories')}
29 ${self.menu('repositories')}
30 %else:
30 %else:
31 ${self.menu('search')}
31 ${self.menu('search')}
32 %endif
32 %endif
33 </%def>
33 </%def>
34 <%def name="main()">
34 <%def name="main()">
35 %if c.repo_name:
35 %if c.repo_name:
36 ${self.repo_context_bar('options')}
36 ${self.repo_context_bar('options')}
37 %endif
37 %endif
38 <div class="box">
38 <div class="box">
39 <!-- box / title -->
39 <!-- box / title -->
40 <div class="title">
40 <div class="title">
41 ${self.breadcrumbs()}
41 ${self.breadcrumbs()}
42 </div>
42 </div>
43 <!-- end box / title -->
43 <!-- end box / title -->
44 %if c.repo_name:
44 %if c.repo_name:
45 ${h.form(h.url('search_repo',repo_name=c.repo_name),method='get')}
45 ${h.form(h.url('search_repo',repo_name=c.repo_name),method='get')}
46 %else:
46 %else:
47 ${h.form(h.url('search'),method='get')}
47 ${h.form(h.url('search'),method='get')}
48 %endif
48 %endif
49 <div class="form">
49 <div class="form">
50 <div class="fields">
50 <div class="fields">
51 <div class="field field-first field-noborder">
51 <div class="field field-first field-noborder">
52 <div class="label">
52 <div class="label">
53 <label for="q">${_('Search term')}</label>
53 <label for="q">${_('Search term')}</label>
54 </div>
54 </div>
55 <div class="input">${h.text('q',c.cur_query,class_="small")}
55 <div class="input">${h.text('q',c.cur_query,class_="small")}
56 <div class="button highlight">
56 <div class="button highlight">
57 <input type="submit" value="${_('Search')}" class="btn"/>
57 <input type="submit" value="${_('Search')}" class="btn"/>
58 </div>
58 </div>
59 </div>
59 </div>
60 <div style="font-weight: bold;clear:both;margin-left:200px">${c.runtime}</div>
60 <div style="font-weight: bold;clear:both;margin-left:200px">${c.runtime}</div>
61 </div>
61 </div>
62
62
63 <div class="field">
63 <div class="field">
64 <div class="label">
64 <div class="label">
65 <label for="type">${_('Search in')}</label>
65 <label for="type">${_('Search in')}</label>
66 </div>
66 </div>
67 <div class="select">
67 <div class="select">
68 ${h.select('type',c.cur_type,[('content',_('File contents')),
68 ${h.select('type',c.cur_type,[('content',_('File contents')),
69 ('commit',_('Commit messages')),
69 ('commit',_('Commit messages')),
70 ('path',_('File names')),
70 ('path',_('File names'))
71 ##('repository',_('Repository names')),
71 ##('repository',_('Repository names'))
72 ])}
72 ])}
73 </div>
73 </div>
74 </div>
74 </div>
75
75
76 </div>
76 </div>
77 </div>
77 </div>
78 ${h.end_form()}
78 ${h.end_form()}
79 <div class="search">
79 <div class="search">
80 %if c.cur_type == 'content':
80 %if c.cur_type == 'content':
81 <%include file='search_content.html'/>
81 <%include file='search_content.html'/>
82 %elif c.cur_type == 'path':
82 %elif c.cur_type == 'path':
83 <%include file='search_path.html'/>
83 <%include file='search_path.html'/>
84 %elif c.cur_type == 'commit':
84 %elif c.cur_type == 'commit':
85 <%include file='search_commit.html'/>
85 <%include file='search_commit.html'/>
86 %elif c.cur_type == 'repository':
86 %elif c.cur_type == 'repository':
87 <%include file='search_repository.html'/>
87 <%include file='search_repository.html'/>
88 %endif
88 %endif
89 </div>
89 </div>
90 </div>
90 </div>
91
91
92 </%def>
92 </%def>
@@ -1,450 +1,450 b''
1 <%inherit file="/base/base.html"/>
1 <%inherit file="/base/base.html"/>
2
2
3 <%def name="title()">
3 <%def name="title()">
4 ${_('%s Statistics') % c.repo_name}
4 ${_('%s Statistics') % c.repo_name}
5 %if c.site_name:
5 %if c.site_name:
6 &middot; ${c.site_name}
6 &middot; ${c.site_name}
7 %endif
7 %endif
8 </%def>
8 </%def>
9
9
10 <%def name="breadcrumbs_links()">
10 <%def name="breadcrumbs_links()">
11 ${_('Statistics')}
11 ${_('Statistics')}
12 </%def>
12 </%def>
13
13
14 <%def name="page_nav()">
14 <%def name="page_nav()">
15 ${self.menu('repositories')}
15 ${self.menu('repositories')}
16 </%def>
16 </%def>
17
17
18 <%def name="head_extra()">
18 <%def name="head_extra()">
19 <link href="${h.url('atom_feed_home',repo_name=c.db_repo.repo_name,api_key=c.authuser.api_key)}" rel="alternate" title="${_('%s ATOM feed') % c.repo_name}" type="application/atom+xml" />
19 <link href="${h.url('atom_feed_home',repo_name=c.db_repo.repo_name,api_key=c.authuser.api_key)}" rel="alternate" title="${_('%s ATOM feed') % c.repo_name}" type="application/atom+xml" />
20 <link href="${h.url('rss_feed_home',repo_name=c.db_repo.repo_name,api_key=c.authuser.api_key)}" rel="alternate" title="${_('%s RSS feed') % c.repo_name}" type="application/rss+xml" />
20 <link href="${h.url('rss_feed_home',repo_name=c.db_repo.repo_name,api_key=c.authuser.api_key)}" rel="alternate" title="${_('%s RSS feed') % c.repo_name}" type="application/rss+xml" />
21 </%def>
21 </%def>
22
22
23 <%def name="main()">
23 <%def name="main()">
24 ${self.repo_context_bar('summary')}
24 ${self.repo_context_bar('summary')}
25 <%
25 <%
26 summary = lambda n:{False:'summary-short'}.get(n)
26 summary = lambda n:{False:'summary-short'}.get(n)
27 %>
27 %>
28 <div class="box">
28 <div class="box">
29 <!-- box / title -->
29 <!-- box / title -->
30 <div class="title">
30 <div class="title">
31 ${self.breadcrumbs()}
31 ${self.breadcrumbs()}
32 </div>
32 </div>
33
33
34 <div class="graph">
34 <div class="graph">
35 <div style="padding:0 10px 10px 17px;">
35 <div style="padding:0 10px 10px 17px;">
36 %if c.no_data:
36 %if c.no_data:
37 ${c.no_data_msg}
37 ${c.no_data_msg}
38 %if h.HasPermissionAll('hg.admin')('enable stats on from summary'):
38 %if h.HasPermissionAll('hg.admin')('enable stats on from summary'):
39 ${h.link_to(_('Enable'),h.url('edit_repo',repo_name=c.repo_name),class_="btn btn-mini")}
39 ${h.link_to(_('Enable'),h.url('edit_repo',repo_name=c.repo_name),class_="btn btn-mini")}
40 %endif
40 %endif
41 %else:
41 %else:
42 ${_('Stats gathered: ')} ${c.stats_percentage}%
42 ${_('Stats gathered: ')} ${c.stats_percentage}%
43 %endif
43 %endif
44 </div>
44 </div>
45 <div id="commit_history" style="width:450px;height:300px;float:left"></div>
45 <div id="commit_history" style="width:450px;height:300px;float:left"></div>
46 <div style="clear: both;height: 10px"></div>
46 <div style="clear: both;height: 10px"></div>
47 <div id="overview" style="width:450px;height:100px;float:left"></div>
47 <div id="overview" style="width:450px;height:100px;float:left"></div>
48
48
49 <div id="legend_data" style="clear:both;margin-top:10px;">
49 <div id="legend_data" style="clear:both;margin-top:10px;">
50 <div id="legend_container"></div>
50 <div id="legend_container"></div>
51 <div id="legend_choices">
51 <div id="legend_choices">
52 <table id="legend_choices_tables" class="noborder" style="font-size:smaller;color:#545454"></table>
52 <table id="legend_choices_tables" class="noborder" style="font-size:smaller;color:#545454"></table>
53 </div>
53 </div>
54 </div>
54 </div>
55 </div>
55 </div>
56 </div>
56 </div>
57
57
58 <script type="text/javascript">
58 <script type="text/javascript">
59 var data = ${c.trending_languages|n};
59 var data = ${c.trending_languages|n};
60 var total = 0;
60 var total = 0;
61 var no_data = true;
61 var no_data = true;
62 var tbl = document.createElement('table');
62 var tbl = document.createElement('table');
63 tbl.setAttribute('class','trending_language_tbl');
63 tbl.setAttribute('class','trending_language_tbl');
64 var cnt = 0;
64 var cnt = 0;
65 for (var i=0;i<data.length;i++){
65 for (var i=0;i<data.length;i++){
66 total+= data[i][1].count;
66 total+= data[i][1].count;
67 }
67 }
68 for (var i=0;i<data.length;i++){
68 for (var i=0;i<data.length;i++){
69 cnt += 1;
69 cnt += 1;
70 no_data = false;
70 no_data = false;
71
71
72 var hide = cnt>2;
72 var hide = cnt>2;
73 var tr = document.createElement('tr');
73 var tr = document.createElement('tr');
74 if (hide){
74 if (hide){
75 tr.setAttribute('style','display:none');
75 tr.setAttribute('style','display:none');
76 tr.setAttribute('class','stats_hidden');
76 tr.setAttribute('class','stats_hidden');
77 }
77 }
78 var k = data[i][0];
78 var k = data[i][0];
79 var obj = data[i][1];
79 var obj = data[i][1];
80 var percentage = Math.round((obj.count/total*100),2);
80 var percentage = Math.round((obj.count/total*100),2);
81
81
82 var td1 = document.createElement('td');
82 var td1 = document.createElement('td');
83 td1.width = 150;
83 td1.width = 150;
84 var trending_language_label = document.createElement('div');
84 var trending_language_label = document.createElement('div');
85 trending_language_label.innerHTML = obj.desc+" ("+k+")";
85 trending_language_label.innerHTML = obj.desc+" ("+k+")";
86 td1.appendChild(trending_language_label);
86 td1.appendChild(trending_language_label);
87
87
88 var td2 = document.createElement('td');
88 var td2 = document.createElement('td');
89 td2.setAttribute('style','padding-right:14px !important');
89 td2.setAttribute('style','padding-right:14px !important');
90 var trending_language = document.createElement('div');
90 var trending_language = document.createElement('div');
91 var nr_files = obj.count+" ${_('files')}";
91 var nr_files = obj.count+" ${_('files')}";
92
92
93 trending_language.title = k+" "+nr_files;
93 trending_language.title = k+" "+nr_files;
94
94
95 if (percentage>22){
95 if (percentage>22){
96 trending_language.innerHTML = "<b style='font-size:0.8em'>"+percentage+"% "+nr_files+ "</b>";
96 trending_language.innerHTML = "<b style='font-size:0.8em'>"+percentage+"% "+nr_files+ "</b>";
97 }
97 }
98 else{
98 else{
99 trending_language.innerHTML = "<b style='font-size:0.8em'>"+percentage+"%</b>";
99 trending_language.innerHTML = "<b style='font-size:0.8em'>"+percentage+"%</b>";
100 }
100 }
101
101
102 trending_language.setAttribute("class", 'trending_language top-right-rounded-corner bottom-right-rounded-corner');
102 trending_language.setAttribute("class", 'trending_language top-right-rounded-corner bottom-right-rounded-corner');
103 trending_language.style.width=percentage+"%";
103 trending_language.style.width=percentage+"%";
104 td2.appendChild(trending_language);
104 td2.appendChild(trending_language);
105
105
106 tr.appendChild(td1);
106 tr.appendChild(td1);
107 tr.appendChild(td2);
107 tr.appendChild(td2);
108 tbl.appendChild(tr);
108 tbl.appendChild(tr);
109 if(cnt == 3){
109 if(cnt == 3){
110 var show_more = document.createElement('tr');
110 var show_more = document.createElement('tr');
111 var td = document.createElement('td');
111 var td = document.createElement('td');
112 lnk = document.createElement('a');
112 lnk = document.createElement('a');
113
113
114 lnk.href='#';
114 lnk.href='#';
115 lnk.innerHTML = "${_('Show more')}";
115 lnk.innerHTML = "${_('Show more')}";
116 lnk.id='code_stats_show_more';
116 lnk.id='code_stats_show_more';
117 td.appendChild(lnk);
117 td.appendChild(lnk);
118
118
119 show_more.appendChild(td);
119 show_more.appendChild(td);
120 show_more.appendChild(document.createElement('td'));
120 show_more.appendChild(document.createElement('td'));
121 tbl.appendChild(show_more);
121 tbl.appendChild(show_more);
122 }
122 }
123
123
124 }
124 }
125
125
126 </script>
126 </script>
127 <script type="text/javascript">
127 <script type="text/javascript">
128 /**
128 /**
129 * Plots summary graph
129 * Plots summary graph
130 *
130 *
131 * @class SummaryPlot
131 * @class SummaryPlot
132 * @param {from} initial from for detailed graph
132 * @param {from} initial from for detailed graph
133 * @param {to} initial to for detailed graph
133 * @param {to} initial to for detailed graph
134 * @param {dataset}
134 * @param {dataset}
135 * @param {overview_dataset}
135 * @param {overview_dataset}
136 */
136 */
137 function SummaryPlot(from,to,dataset,overview_dataset) {
137 function SummaryPlot(from,to,dataset,overview_dataset) {
138 var initial_ranges = {
138 var initial_ranges = {
139 "xaxis":{
139 "xaxis":{
140 "from":from,
140 "from":from,
141 "to":to,
141 "to":to
142 },
142 }
143 };
143 };
144 var dataset = dataset;
144 var dataset = dataset;
145 var overview_dataset = [overview_dataset];
145 var overview_dataset = [overview_dataset];
146 var choiceContainer = YUD.get("legend_choices");
146 var choiceContainer = YUD.get("legend_choices");
147 var choiceContainerTable = YUD.get("legend_choices_tables");
147 var choiceContainerTable = YUD.get("legend_choices_tables");
148 var plotContainer = YUD.get('commit_history');
148 var plotContainer = YUD.get('commit_history');
149 var overviewContainer = YUD.get('overview');
149 var overviewContainer = YUD.get('overview');
150
150
151 var plot_options = {
151 var plot_options = {
152 bars: {show:true,align:'center',lineWidth:4},
152 bars: {show:true, align: 'center', lineWidth: 4},
153 legend: {show:true, container:"legend_container"},
153 legend: {show:true, container: "legend_container"},
154 points: {show:true,radius:0,fill:false},
154 points: {show:true, radius: 0, fill: false},
155 yaxis: {tickDecimals:0,},
155 yaxis: {tickDecimals: 0},
156 xaxis: {
156 xaxis: {
157 mode: "time",
157 mode: "time",
158 timeformat: "%d/%m",
158 timeformat: "%d/%m",
159 min:from,
159 min: from,
160 max:to,
160 max: to
161 },
161 },
162 grid: {
162 grid: {
163 hoverable: true,
163 hoverable: true,
164 clickable: true,
164 clickable: true,
165 autoHighlight:true,
165 autoHighlight: true,
166 color: "#999"
166 color: "#999"
167 },
167 },
168 //selection: {mode: "x"}
168 //selection: {mode: "x"}
169 };
169 };
170 var overview_options = {
170 var overview_options = {
171 legend:{show:false},
171 legend:{show:false},
172 bars: {show:true,barWidth: 2,},
172 bars: {show:true, barWidth: 2},
173 shadowSize: 0,
173 shadowSize: 0,
174 xaxis: {mode: "time", timeformat: "%d/%m/%y",},
174 xaxis: {mode: "time", timeformat: "%d/%m/%y"},
175 yaxis: {ticks: 3, min: 0,tickDecimals:0,},
175 yaxis: {ticks: 3, min: 0, tickDecimals:0},
176 grid: {color: "#999",},
176 grid: {color: "#999"},
177 selection: {mode: "x"}
177 selection: {mode: "x"}
178 };
178 };
179
179
180 /**
180 /**
181 *get dummy data needed in few places
181 *get dummy data needed in few places
182 */
182 */
183 function getDummyData(label){
183 function getDummyData(label){
184 return {"label":label,
184 return {"label":label,
185 "data":[{"time":0,
185 "data":[{"time":0,
186 "commits":0,
186 "commits":0,
187 "added":0,
187 "added":0,
188 "changed":0,
188 "changed":0,
189 "removed":0,
189 "removed":0
190 }],
190 }],
191 "schema":["commits"],
191 "schema":["commits"],
192 "color":'#ffffff',
192 "color":'#ffffff'
193 }
193 }
194 }
194 }
195
195
196 /**
196 /**
197 * generate checkboxes accordindly to data
197 * generate checkboxes accordindly to data
198 * @param keys
198 * @param keys
199 * @returns
199 * @returns
200 */
200 */
201 function generateCheckboxes(data) {
201 function generateCheckboxes(data) {
202 //append checkboxes
202 //append checkboxes
203 var i = 0;
203 var i = 0;
204 choiceContainerTable.innerHTML = '';
204 choiceContainerTable.innerHTML = '';
205 for(var pos in data) {
205 for(var pos in data) {
206
206
207 data[pos].color = i;
207 data[pos].color = i;
208 i++;
208 i++;
209 if(data[pos].label != ''){
209 if(data[pos].label != ''){
210 choiceContainerTable.innerHTML +=
210 choiceContainerTable.innerHTML +=
211 '<tr><td><input type="checkbox" id="id_user_{0}" name="{0}" checked="checked" /> \
211 '<tr><td><input type="checkbox" id="id_user_{0}" name="{0}" checked="checked" /> \
212 <label for="id_user_{0}">{0}</label></td></tr>'.format(data[pos].label);
212 <label for="id_user_{0}">{0}</label></td></tr>'.format(data[pos].label);
213 }
213 }
214 }
214 }
215 }
215 }
216
216
217 /**
217 /**
218 * ToolTip show
218 * ToolTip show
219 */
219 */
220 function showTooltip(x, y, contents) {
220 function showTooltip(x, y, contents) {
221 var div=document.getElementById('tooltip');
221 var div=document.getElementById('tooltip');
222 if(!div) {
222 if(!div) {
223 div = document.createElement('div');
223 div = document.createElement('div');
224 div.id="tooltip";
224 div.id="tooltip";
225 div.style.position="absolute";
225 div.style.position="absolute";
226 div.style.border='1px solid #fdd';
226 div.style.border='1px solid #fdd';
227 div.style.padding='2px';
227 div.style.padding='2px';
228 div.style.backgroundColor='#fee';
228 div.style.backgroundColor='#fee';
229 document.body.appendChild(div);
229 document.body.appendChild(div);
230 }
230 }
231 YUD.setStyle(div, 'opacity', 0);
231 YUD.setStyle(div, 'opacity', 0);
232 div.innerHTML = contents;
232 div.innerHTML = contents;
233 div.style.top=(y + 5) + "px";
233 div.style.top=(y + 5) + "px";
234 div.style.left=(x + 5) + "px";
234 div.style.left=(x + 5) + "px";
235
235
236 var anim = new YAHOO.util.Anim(div, {opacity: {to: 0.8}}, 0.2);
236 var anim = new YAHOO.util.Anim(div, {opacity: {to: 0.8}}, 0.2);
237 anim.animate();
237 anim.animate();
238 }
238 }
239
239
240 /**
240 /**
241 * This function will detect if selected period has some changesets
241 * This function will detect if selected period has some changesets
242 for this user if it does this data is then pushed for displaying
242 for this user if it does this data is then pushed for displaying
243 Additionally it will only display users that are selected by the checkbox
243 Additionally it will only display users that are selected by the checkbox
244 */
244 */
245 function getDataAccordingToRanges(ranges) {
245 function getDataAccordingToRanges(ranges) {
246
246
247 var data = [];
247 var data = [];
248 var new_dataset = {};
248 var new_dataset = {};
249 var keys = [];
249 var keys = [];
250 var max_commits = 0;
250 var max_commits = 0;
251 for(var key in dataset){
251 for(var key in dataset){
252
252
253 for(var ds in dataset[key].data){
253 for(var ds in dataset[key].data){
254 commit_data = dataset[key].data[ds];
254 commit_data = dataset[key].data[ds];
255 if (commit_data.time >= ranges.xaxis.from && commit_data.time <= ranges.xaxis.to){
255 if (commit_data.time >= ranges.xaxis.from && commit_data.time <= ranges.xaxis.to){
256
256
257 if(new_dataset[key] === undefined){
257 if(new_dataset[key] === undefined){
258 new_dataset[key] = {data:[],schema:["commits"],label:key};
258 new_dataset[key] = {data:[],schema:["commits"],label:key};
259 }
259 }
260 new_dataset[key].data.push(commit_data);
260 new_dataset[key].data.push(commit_data);
261 }
261 }
262 }
262 }
263 if (new_dataset[key] !== undefined){
263 if (new_dataset[key] !== undefined){
264 data.push(new_dataset[key]);
264 data.push(new_dataset[key]);
265 }
265 }
266 }
266 }
267
267
268 if (data.length > 0){
268 if (data.length > 0){
269 return data;
269 return data;
270 }
270 }
271 else{
271 else{
272 //just return dummy data for graph to plot itself
272 //just return dummy data for graph to plot itself
273 return [getDummyData('')];
273 return [getDummyData('')];
274 }
274 }
275 }
275 }
276
276
277 /**
277 /**
278 * redraw using new checkbox data
278 * redraw using new checkbox data
279 */
279 */
280 function plotchoiced(e,args){
280 function plotchoiced(e,args){
281 var cur_data = args[0];
281 var cur_data = args[0];
282 var cur_ranges = args[1];
282 var cur_ranges = args[1];
283
283
284 var new_data = [];
284 var new_data = [];
285 var inputs = choiceContainer.getElementsByTagName("input");
285 var inputs = choiceContainer.getElementsByTagName("input");
286
286
287 //show only checked labels
287 //show only checked labels
288 for(var i=0; i<inputs.length; i++) {
288 for(var i=0; i<inputs.length; i++) {
289 var checkbox_key = inputs[i].name;
289 var checkbox_key = inputs[i].name;
290
290
291 if(inputs[i].checked){
291 if(inputs[i].checked){
292 for(var d in cur_data){
292 for(var d in cur_data){
293 if(cur_data[d].label == checkbox_key){
293 if(cur_data[d].label == checkbox_key){
294 new_data.push(cur_data[d]);
294 new_data.push(cur_data[d]);
295 }
295 }
296 }
296 }
297 }
297 }
298 else{
298 else{
299 //push dummy data to not hide the label
299 //push dummy data to not hide the label
300 new_data.push(getDummyData(checkbox_key));
300 new_data.push(getDummyData(checkbox_key));
301 }
301 }
302 }
302 }
303
303
304 var new_options = YAHOO.lang.merge(plot_options, {
304 var new_options = YAHOO.lang.merge(plot_options, {
305 xaxis: {
305 xaxis: {
306 min: cur_ranges.xaxis.from,
306 min: cur_ranges.xaxis.from,
307 max: cur_ranges.xaxis.to,
307 max: cur_ranges.xaxis.to,
308 mode:"time",
308 mode: "time",
309 timeformat: "%d/%m",
309 timeformat: "%d/%m"
310 },
310 }
311 });
311 });
312 if (!new_data){
312 if (!new_data){
313 new_data = [[0,1]];
313 new_data = [[0,1]];
314 }
314 }
315 // do the zooming
315 // do the zooming
316 plot = YAHOO.widget.Flot(plotContainer, new_data, new_options);
316 plot = YAHOO.widget.Flot(plotContainer, new_data, new_options);
317
317
318 plot.subscribe("plotselected", plotselected);
318 plot.subscribe("plotselected", plotselected);
319
319
320 //resubscribe plothover
320 //resubscribe plothover
321 plot.subscribe("plothover", plothover);
321 plot.subscribe("plothover", plothover);
322
322
323 // don't fire event on the overview to prevent eternal loop
323 // don't fire event on the overview to prevent eternal loop
324 overview.setSelection(cur_ranges, true);
324 overview.setSelection(cur_ranges, true);
325
325
326 }
326 }
327
327
328 /**
328 /**
329 * plot only selected items from overview
329 * plot only selected items from overview
330 * @param ranges
330 * @param ranges
331 * @returns
331 * @returns
332 */
332 */
333 function plotselected(ranges,cur_data) {
333 function plotselected(ranges,cur_data) {
334 //updates the data for new plot
334 //updates the data for new plot
335 var data = getDataAccordingToRanges(ranges);
335 var data = getDataAccordingToRanges(ranges);
336 generateCheckboxes(data);
336 generateCheckboxes(data);
337
337
338 var new_options = YAHOO.lang.merge(plot_options, {
338 var new_options = YAHOO.lang.merge(plot_options, {
339 xaxis: {
339 xaxis: {
340 min: ranges.xaxis.from,
340 min: ranges.xaxis.from,
341 max: ranges.xaxis.to,
341 max: ranges.xaxis.to,
342 mode:"time",
342 mode:"time",
343 timeformat: "%d/%m",
343 timeformat: "%d/%m"
344 },
344 }
345 });
345 });
346 // do the zooming
346 // do the zooming
347 plot = YAHOO.widget.Flot(plotContainer, data, new_options);
347 plot = YAHOO.widget.Flot(plotContainer, data, new_options);
348
348
349 plot.subscribe("plotselected", plotselected);
349 plot.subscribe("plotselected", plotselected);
350
350
351 //resubscribe plothover
351 //resubscribe plothover
352 plot.subscribe("plothover", plothover);
352 plot.subscribe("plothover", plothover);
353
353
354 // don't fire event on the overview to prevent eternal loop
354 // don't fire event on the overview to prevent eternal loop
355 overview.setSelection(ranges, true);
355 overview.setSelection(ranges, true);
356
356
357 //resubscribe choiced
357 //resubscribe choiced
358 YUE.on(choiceContainer.getElementsByTagName("input"), "click", plotchoiced, [data, ranges]);
358 YUE.on(choiceContainer.getElementsByTagName("input"), "click", plotchoiced, [data, ranges]);
359 }
359 }
360
360
361 var previousPoint = null;
361 var previousPoint = null;
362
362
363 function plothover(o) {
363 function plothover(o) {
364 var pos = o.pos;
364 var pos = o.pos;
365 var item = o.item;
365 var item = o.item;
366
366
367 //YUD.get("x").innerHTML = pos.x.toFixed(2);
367 //YUD.get("x").innerHTML = pos.x.toFixed(2);
368 //YUD.get("y").innerHTML = pos.y.toFixed(2);
368 //YUD.get("y").innerHTML = pos.y.toFixed(2);
369 if (item) {
369 if (item) {
370 if (previousPoint != item.datapoint) {
370 if (previousPoint != item.datapoint) {
371 previousPoint = item.datapoint;
371 previousPoint = item.datapoint;
372
372
373 var tooltip = YUD.get("tooltip");
373 var tooltip = YUD.get("tooltip");
374 if(tooltip) {
374 if(tooltip) {
375 tooltip.parentNode.removeChild(tooltip);
375 tooltip.parentNode.removeChild(tooltip);
376 }
376 }
377 var x = item.datapoint.x.toFixed(2);
377 var x = item.datapoint.x.toFixed(2);
378 var y = item.datapoint.y.toFixed(2);
378 var y = item.datapoint.y.toFixed(2);
379
379
380 if (!item.series.label){
380 if (!item.series.label){
381 item.series.label = 'commits';
381 item.series.label = 'commits';
382 }
382 }
383 var d = new Date(x*1000);
383 var d = new Date(x*1000);
384 var fd = d.toDateString()
384 var fd = d.toDateString()
385 var nr_commits = parseInt(y);
385 var nr_commits = parseInt(y);
386
386
387 var cur_data = dataset[item.series.label].data[item.dataIndex];
387 var cur_data = dataset[item.series.label].data[item.dataIndex];
388 var added = cur_data.added;
388 var added = cur_data.added;
389 var changed = cur_data.changed;
389 var changed = cur_data.changed;
390 var removed = cur_data.removed;
390 var removed = cur_data.removed;
391
391
392 var nr_commits_suffix = " ${_('commits')} ";
392 var nr_commits_suffix = " ${_('commits')} ";
393 var added_suffix = " ${_('files added')} ";
393 var added_suffix = " ${_('files added')} ";
394 var changed_suffix = " ${_('files changed')} ";
394 var changed_suffix = " ${_('files changed')} ";
395 var removed_suffix = " ${_('files removed')} ";
395 var removed_suffix = " ${_('files removed')} ";
396
396
397 if(nr_commits == 1){nr_commits_suffix = " ${_('commit')} ";}
397 if(nr_commits == 1){nr_commits_suffix = " ${_('commit')} ";}
398 if(added==1){added_suffix=" ${_('file added')} ";}
398 if(added==1){added_suffix=" ${_('file added')} ";}
399 if(changed==1){changed_suffix=" ${_('file changed')} ";}
399 if(changed==1){changed_suffix=" ${_('file changed')} ";}
400 if(removed==1){removed_suffix=" ${_('file removed')} ";}
400 if(removed==1){removed_suffix=" ${_('file removed')} ";}
401
401
402 showTooltip(item.pageX, item.pageY, item.series.label + " on " + fd
402 showTooltip(item.pageX, item.pageY, item.series.label + " on " + fd
403 +'<br/>'+
403 +'<br/>'+
404 nr_commits + nr_commits_suffix+'<br/>'+
404 nr_commits + nr_commits_suffix+'<br/>'+
405 added + added_suffix +'<br/>'+
405 added + added_suffix +'<br/>'+
406 changed + changed_suffix + '<br/>'+
406 changed + changed_suffix + '<br/>'+
407 removed + removed_suffix + '<br/>');
407 removed + removed_suffix + '<br/>');
408 }
408 }
409 }
409 }
410 else {
410 else {
411 var tooltip = YUD.get("tooltip");
411 var tooltip = YUD.get("tooltip");
412
412
413 if(tooltip) {
413 if(tooltip) {
414 tooltip.parentNode.removeChild(tooltip);
414 tooltip.parentNode.removeChild(tooltip);
415 }
415 }
416 previousPoint = null;
416 previousPoint = null;
417 }
417 }
418 }
418 }
419
419
420 /**
420 /**
421 * MAIN EXECUTION
421 * MAIN EXECUTION
422 */
422 */
423
423
424 var data = getDataAccordingToRanges(initial_ranges);
424 var data = getDataAccordingToRanges(initial_ranges);
425 generateCheckboxes(data);
425 generateCheckboxes(data);
426
426
427 //main plot
427 //main plot
428 var plot = YAHOO.widget.Flot(plotContainer,data,plot_options);
428 var plot = YAHOO.widget.Flot(plotContainer,data,plot_options);
429
429
430 //overview
430 //overview
431 var overview = YAHOO.widget.Flot(overviewContainer,
431 var overview = YAHOO.widget.Flot(overviewContainer,
432 overview_dataset, overview_options);
432 overview_dataset, overview_options);
433
433
434 //show initial selection on overview
434 //show initial selection on overview
435 overview.setSelection(initial_ranges);
435 overview.setSelection(initial_ranges);
436
436
437 plot.subscribe("plotselected", plotselected);
437 plot.subscribe("plotselected", plotselected);
438 plot.subscribe("plothover", plothover)
438 plot.subscribe("plothover", plothover)
439
439
440 overview.subscribe("plotselected", function (ranges) {
440 overview.subscribe("plotselected", function (ranges) {
441 plot.setSelection(ranges);
441 plot.setSelection(ranges);
442 });
442 });
443
443
444 // user choices on overview
444 // user choices on overview
445 YUE.on(choiceContainer.getElementsByTagName("input"), "click", plotchoiced, [data, initial_ranges]);
445 YUE.on(choiceContainer.getElementsByTagName("input"), "click", plotchoiced, [data, initial_ranges]);
446 }
446 }
447 SummaryPlot(${c.ts_min},${c.ts_max},${c.commit_data|n},${c.overview_data|n});
447 SummaryPlot(${c.ts_min},${c.ts_max},${c.commit_data|n},${c.overview_data|n});
448 </script>
448 </script>
449
449
450 </%def>
450 </%def>
@@ -1,400 +1,400 b''
1 <%inherit file="/base/base.html"/>
1 <%inherit file="/base/base.html"/>
2
2
3 <%def name="title()">
3 <%def name="title()">
4 ${_('%s Summary') % c.repo_name}
4 ${_('%s Summary') % c.repo_name}
5 %if c.site_name:
5 %if c.site_name:
6 &middot; ${c.site_name}
6 &middot; ${c.site_name}
7 %endif
7 %endif
8 </%def>
8 </%def>
9
9
10 <%def name="breadcrumbs_links()">
10 <%def name="breadcrumbs_links()">
11 ${_('Summary')}
11 ${_('Summary')}
12
12
13 ## locking icon
13 ## locking icon
14 %if c.db_repo.enable_locking:
14 %if c.db_repo.enable_locking:
15 %if c.db_repo.locked[0]:
15 %if c.db_repo.locked[0]:
16 <span class="locking_locked tooltip" title="${_('Repository locked by %s') % h.person_by_id(c.db_repo.locked[0])}"></span>
16 <span class="locking_locked tooltip" title="${_('Repository locked by %s') % h.person_by_id(c.db_repo.locked[0])}"></span>
17 %else:
17 %else:
18 <span class="locking_unlocked tooltip" title="${_('Repository unlocked')}"></span>
18 <span class="locking_unlocked tooltip" title="${_('Repository unlocked')}"></span>
19 %endif
19 %endif
20 %endif
20 %endif
21
21
22 ##FORK
22 ##FORK
23 %if c.db_repo.fork:
23 %if c.db_repo.fork:
24 <span>
24 <span>
25 - <i class="icon-code-fork"></i> ${_('Fork of')} "<a href="${h.url('summary_home',repo_name=c.db_repo.fork.repo_name)}">${c.db_repo.fork.repo_name}</a>"
25 - <i class="icon-code-fork"></i> ${_('Fork of')} "<a href="${h.url('summary_home',repo_name=c.db_repo.fork.repo_name)}">${c.db_repo.fork.repo_name}</a>"
26 </span>
26 </span>
27 %endif
27 %endif
28
28
29 ##REMOTE
29 ##REMOTE
30 %if c.db_repo.clone_uri:
30 %if c.db_repo.clone_uri:
31 <span>
31 <span>
32 - <i class="icon-code-fork"></i> ${_('Clone from')} "<a href="${h.url(str(h.hide_credentials(c.db_repo.clone_uri)))}">${h.hide_credentials(c.db_repo.clone_uri)}</a>"
32 - <i class="icon-code-fork"></i> ${_('Clone from')} "<a href="${h.url(str(h.hide_credentials(c.db_repo.clone_uri)))}">${h.hide_credentials(c.db_repo.clone_uri)}</a>"
33 <span>
33 <span>
34 %endif
34 %endif
35 </%def>
35 </%def>
36
36
37 <%def name="page_nav()">
37 <%def name="page_nav()">
38 ${self.menu('repositories')}
38 ${self.menu('repositories')}
39 </%def>
39 </%def>
40
40
41 <%def name="head_extra()">
41 <%def name="head_extra()">
42 <link href="${h.url('atom_feed_home',repo_name=c.db_repo.repo_name,api_key=c.authuser.api_key)}" rel="alternate" title="${_('%s ATOM feed') % c.repo_name}" type="application/atom+xml" />
42 <link href="${h.url('atom_feed_home',repo_name=c.db_repo.repo_name,api_key=c.authuser.api_key)}" rel="alternate" title="${_('%s ATOM feed') % c.repo_name}" type="application/atom+xml" />
43 <link href="${h.url('rss_feed_home',repo_name=c.db_repo.repo_name,api_key=c.authuser.api_key)}" rel="alternate" title="${_('%s RSS feed') % c.repo_name}" type="application/rss+xml" />
43 <link href="${h.url('rss_feed_home',repo_name=c.db_repo.repo_name,api_key=c.authuser.api_key)}" rel="alternate" title="${_('%s RSS feed') % c.repo_name}" type="application/rss+xml" />
44
44
45 <script>
45 <script>
46 redirect_hash_branch = function(){
46 redirect_hash_branch = function(){
47 var branch = window.location.hash.replace(/^#(.*)/, '$1');
47 var branch = window.location.hash.replace(/^#(.*)/, '$1');
48 if (branch){
48 if (branch){
49 window.location = "${h.url('changelog_home',repo_name=c.repo_name,branch='__BRANCH__')}"
49 window.location = "${h.url('changelog_home',repo_name=c.repo_name,branch='__BRANCH__')}"
50 .replace('__BRANCH__',branch);
50 .replace('__BRANCH__',branch);
51 }
51 }
52 }
52 }
53 redirect_hash_branch();
53 redirect_hash_branch();
54 window.onhashchange = function() {
54 window.onhashchange = function() {
55 redirect_hash_branch();
55 redirect_hash_branch();
56 };
56 };
57 </script>
57 </script>
58
58
59 </%def>
59 </%def>
60
60
61 <%def name="main()">
61 <%def name="main()">
62 ${self.repo_context_bar('summary')}
62 ${self.repo_context_bar('summary')}
63 <%
63 <%
64 summary = lambda n:{False:'summary-short'}.get(n)
64 summary = lambda n:{False:'summary-short'}.get(n)
65 %>
65 %>
66 <div class="box">
66 <div class="box">
67 <!-- box / title -->
67 <!-- box / title -->
68 <div class="title">
68 <div class="title">
69 ${self.breadcrumbs()}
69 ${self.breadcrumbs()}
70 </div>
70 </div>
71 <!-- end box / title -->
71 <!-- end box / title -->
72 <div class="form">
72 <div class="form">
73 <div id="summary" class="fields">
73 <div id="summary" class="fields">
74 <div class="field">
74 <div class="field">
75 <div class="label-summary">
75 <div class="label-summary">
76 <label>${_('Clone url')}:</label>
76 <label>${_('Clone url')}:</label>
77 </div>
77 </div>
78 <div class="input ${summary(c.show_stats)}">
78 <div class="input ${summary(c.show_stats)}">
79 <input style="width:80%" type="text" id="clone_url" readonly="readonly" value="${c.clone_repo_url}"/>
79 <input style="width:80%" type="text" id="clone_url" readonly="readonly" value="${c.clone_repo_url}"/>
80 <input style="display:none;width:80%" type="text" id="clone_url_id" readonly="readonly" value="${c.clone_repo_url_id}"/>
80 <input style="display:none;width:80%" type="text" id="clone_url_id" readonly="readonly" value="${c.clone_repo_url_id}"/>
81 <div style="display:none" id="clone_by_name" class="btn btn-small clone">${_('Show by Name')}</div>
81 <div style="display:none" id="clone_by_name" class="btn btn-small clone">${_('Show by Name')}</div>
82 <div id="clone_by_id" class="btn btn-small clone">${_('Show by ID')}</div>
82 <div id="clone_by_id" class="btn btn-small clone">${_('Show by ID')}</div>
83 </div>
83 </div>
84 </div>
84 </div>
85
85
86 <div class="field">
86 <div class="field">
87 <div class="label-summary">
87 <div class="label-summary">
88 <label>${_('Description')}:</label>
88 <label>${_('Description')}:</label>
89 </div>
89 </div>
90 %if c.visual.stylify_metatags:
90 %if c.visual.stylify_metatags:
91 <div class="input ${summary(c.show_stats)} desc">${h.urlify_text(h.desc_stylize(c.db_repo.description))}</div>
91 <div class="input ${summary(c.show_stats)} desc">${h.urlify_text(h.desc_stylize(c.db_repo.description))}</div>
92 %else:
92 %else:
93 <div class="input ${summary(c.show_stats)} desc">${h.urlify_text(c.db_repo.description)}</div>
93 <div class="input ${summary(c.show_stats)} desc">${h.urlify_text(c.db_repo.description)}</div>
94 %endif
94 %endif
95 </div>
95 </div>
96
96
97 <div class="field">
97 <div class="field">
98 <div class="label-summary">
98 <div class="label-summary">
99 <label>${_('Trending files')}:</label>
99 <label>${_('Trending files')}:</label>
100 </div>
100 </div>
101 <div class="input ${summary(c.show_stats)}">
101 <div class="input ${summary(c.show_stats)}">
102 %if c.show_stats:
102 %if c.show_stats:
103 <div id="lang_stats"></div>
103 <div id="lang_stats"></div>
104 %else:
104 %else:
105 ${_('Statistics are disabled for this repository')}
105 ${_('Statistics are disabled for this repository')}
106 %if h.HasPermissionAll('hg.admin')('enable stats on from summary'):
106 %if h.HasPermissionAll('hg.admin')('enable stats on from summary'):
107 ${h.link_to(_('Enable'),h.url('edit_repo',repo_name=c.repo_name, anchor='repo_enable_statistics'),class_="btn btn-mini")}
107 ${h.link_to(_('Enable'),h.url('edit_repo',repo_name=c.repo_name, anchor='repo_enable_statistics'),class_="btn btn-mini")}
108 %endif
108 %endif
109 %endif
109 %endif
110 </div>
110 </div>
111 </div>
111 </div>
112
112
113 <div class="field">
113 <div class="field">
114 <div class="label-summary">
114 <div class="label-summary">
115 <label>${_('Download')}:</label>
115 <label>${_('Download')}:</label>
116 </div>
116 </div>
117 <div class="input ${summary(c.show_stats)}">
117 <div class="input ${summary(c.show_stats)}">
118 %if len(c.db_repo_scm_instance.revisions) == 0:
118 %if len(c.db_repo_scm_instance.revisions) == 0:
119 ${_('There are no downloads yet')}
119 ${_('There are no downloads yet')}
120 %elif not c.enable_downloads:
120 %elif not c.enable_downloads:
121 ${_('Downloads are disabled for this repository')}
121 ${_('Downloads are disabled for this repository')}
122 %if h.HasPermissionAll('hg.admin')('enable downloads on from summary'):
122 %if h.HasPermissionAll('hg.admin')('enable downloads on from summary'):
123 ${h.link_to(_('Enable'),h.url('edit_repo',repo_name=c.repo_name, anchor='repo_enable_downloads'),class_="btn btn-mini")}
123 ${h.link_to(_('Enable'),h.url('edit_repo',repo_name=c.repo_name, anchor='repo_enable_downloads'),class_="btn btn-mini")}
124 %endif
124 %endif
125 %else:
125 %else:
126 <span id="${'zip_link'}">
126 <span id="${'zip_link'}">
127 <a class="btn btn-small" href="${h.url('files_archive_home',repo_name=c.db_repo.repo_name,fname='tip.zip')}"><i class="icon-archive"></i> ${_('Download as zip')}</a>
127 <a class="btn btn-small" href="${h.url('files_archive_home',repo_name=c.db_repo.repo_name,fname='tip.zip')}"><i class="icon-archive"></i> ${_('Download as zip')}</a>
128 </span>
128 </span>
129 ${h.hidden('download_options')}
129 ${h.hidden('download_options')}
130 <span style="vertical-align: bottom">
130 <span style="vertical-align: bottom">
131 <input id="archive_subrepos" type="checkbox" name="subrepos" />
131 <input id="archive_subrepos" type="checkbox" name="subrepos" />
132 <label for="archive_subrepos" class="tooltip" title="${h.tooltip(_('Check this to download archive with subrepos'))}" >${_('with subrepos')}</label>
132 <label for="archive_subrepos" class="tooltip" title="${h.tooltip(_('Check this to download archive with subrepos'))}" >${_('with subrepos')}</label>
133 </span>
133 </span>
134 %endif
134 %endif
135 </div>
135 </div>
136 </div>
136 </div>
137 </div>
137 </div>
138 <div id="summary-menu-stats">
138 <div id="summary-menu-stats">
139 <ul>
139 <ul>
140 <li>
140 <li>
141 <a title="${_('Owner')} ${c.db_repo.user.email}">
141 <a title="${_('Owner')} ${c.db_repo.user.email}">
142 <i class="icon-user"></i> ${c.db_repo.user.username}
142 <i class="icon-user"></i> ${c.db_repo.user.username}
143 <div class="gravatar" style="float: right; margin: 0px 0px 0px 0px" title="${c.db_repo.user.name} ${c.db_repo.user.lastname}">
143 <div class="gravatar" style="float: right; margin: 0px 0px 0px 0px" title="${c.db_repo.user.name} ${c.db_repo.user.lastname}">
144 <img alt="gravatar" src="${h.gravatar_url(c.db_repo.user.email, 18)}"/>
144 <img alt="gravatar" src="${h.gravatar_url(c.db_repo.user.email, 18)}"/>
145 </div>
145 </div>
146 </a>
146 </a>
147 </li>
147 </li>
148 <li>
148 <li>
149 <a title="${_('Followers')}" href="${h.url('repo_followers_home',repo_name=c.repo_name)}">
149 <a title="${_('Followers')}" href="${h.url('repo_followers_home',repo_name=c.repo_name)}">
150 <i class="icon-heart"></i> ${_('Followers')}
150 <i class="icon-heart"></i> ${_('Followers')}
151 <span class="stats-bullet" id="current_followers_count">${c.repository_followers}</span>
151 <span class="stats-bullet" id="current_followers_count">${c.repository_followers}</span>
152 </a>
152 </a>
153 </li>
153 </li>
154 <li>
154 <li>
155 <a title="${_('Forks')}" href="${h.url('repo_forks_home',repo_name=c.repo_name)}">
155 <a title="${_('Forks')}" href="${h.url('repo_forks_home',repo_name=c.repo_name)}">
156 <i class="icon-code-fork"></i> ${_('Forks')}
156 <i class="icon-code-fork"></i> ${_('Forks')}
157 <span class="stats-bullet">${c.repository_forks}</span>
157 <span class="stats-bullet">${c.repository_forks}</span>
158 </a>
158 </a>
159 </li>
159 </li>
160
160
161 %if c.authuser.username != 'default':
161 %if c.authuser.username != 'default':
162 <li class="repo_size">
162 <li class="repo_size">
163 <a href="#" onclick="javascript:showRepoSize('repo_size_2','${c.db_repo.repo_name}','${str(h.get_token())}')"><i class="icon-archive"></i> ${_('Repository Size')}</a>
163 <a href="#" onclick="javascript:showRepoSize('repo_size_2','${c.db_repo.repo_name}','${str(h.get_token())}')"><i class="icon-archive"></i> ${_('Repository Size')}</a>
164 <span class="stats-bullet" id="repo_size_2"></span>
164 <span class="stats-bullet" id="repo_size_2"></span>
165 </li>
165 </li>
166 %endif
166 %endif
167
167
168 <li>
168 <li>
169 %if c.authuser.username != 'default':
169 %if c.authuser.username != 'default':
170 <a href="${h.url('atom_feed_home',repo_name=c.db_repo.repo_name,api_key=c.authuser.api_key)}"><i class="icon-rss-sign"></i> ${_('Feed')}</a>
170 <a href="${h.url('atom_feed_home',repo_name=c.db_repo.repo_name,api_key=c.authuser.api_key)}"><i class="icon-rss-sign"></i> ${_('Feed')}</a>
171 %else:
171 %else:
172 <a href="${h.url('atom_feed_home',repo_name=c.db_repo.repo_name)}"><i class="icon-rss-sign"></i> ${_('Feed')}</a>
172 <a href="${h.url('atom_feed_home',repo_name=c.db_repo.repo_name)}"><i class="icon-rss-sign"></i> ${_('Feed')}</a>
173 %endif
173 %endif
174 </li>
174 </li>
175
175
176 %if c.show_stats:
176 %if c.show_stats:
177 <li>
177 <li>
178 <a title="${_('Statistics')}" href="${h.url('repo_stats_home',repo_name=c.repo_name)}">
178 <a title="${_('Statistics')}" href="${h.url('repo_stats_home',repo_name=c.repo_name)}">
179 <i class="icon-bar-chart"></i> ${_('Statistics')}
179 <i class="icon-bar-chart"></i> ${_('Statistics')}
180 </a>
180 </a>
181 </li>
181 </li>
182 %endif
182 %endif
183 </ul>
183 </ul>
184 </div>
184 </div>
185 </div>
185 </div>
186 </div>
186 </div>
187
187
188
188
189 <div class="box">
189 <div class="box">
190 <div class="title">
190 <div class="title">
191 <div class="breadcrumbs">
191 <div class="breadcrumbs">
192 %if c.repo_changesets:
192 %if c.repo_changesets:
193 ${h.link_to(_('Latest changes'),h.url('changelog_home',repo_name=c.repo_name))}
193 ${h.link_to(_('Latest changes'),h.url('changelog_home',repo_name=c.repo_name))}
194 %else:
194 %else:
195 ${_('Quick start')}
195 ${_('Quick start')}
196 %endif
196 %endif
197 </div>
197 </div>
198 </div>
198 </div>
199 <div class="table">
199 <div class="table">
200 <div id="shortlog_data">
200 <div id="shortlog_data">
201 <%include file='../changelog/changelog_summary_data.html'/>
201 <%include file='../changelog/changelog_summary_data.html'/>
202 </div>
202 </div>
203 </div>
203 </div>
204 </div>
204 </div>
205
205
206 %if c.readme_data:
206 %if c.readme_data:
207 <div id="readme" class="anchor">
207 <div id="readme" class="anchor">
208 <div class="box" style="background-color: #FAFAFA">
208 <div class="box" style="background-color: #FAFAFA">
209 <div class="title" title="${_('Readme file from revision %s:%s') % (c.db_repo.landing_rev[0], c.db_repo.landing_rev[1])}">
209 <div class="title" title="${_('Readme file from revision %s:%s') % (c.db_repo.landing_rev[0], c.db_repo.landing_rev[1])}">
210 <div class="breadcrumbs">
210 <div class="breadcrumbs">
211 <a href="${h.url('files_home',repo_name=c.repo_name,revision='tip',f_path=c.readme_file)}">${c.readme_file}</a>
211 <a href="${h.url('files_home',repo_name=c.repo_name,revision='tip',f_path=c.readme_file)}">${c.readme_file}</a>
212 </div>
212 </div>
213 </div>
213 </div>
214 <div class="readme">
214 <div class="readme">
215 <div class="readme_box">
215 <div class="readme_box">
216 ${c.readme_data|n}
216 ${c.readme_data|n}
217 </div>
217 </div>
218 </div>
218 </div>
219 </div>
219 </div>
220 </div>
220 </div>
221 %endif
221 %endif
222
222
223 <script type="text/javascript">
223 <script type="text/javascript">
224 $(document).ready(function(){
224 $(document).ready(function(){
225 var $clone_url = $('#clone_url');
225 var $clone_url = $('#clone_url');
226 var $clone_url_id = $('#clone_url_id');
226 var $clone_url_id = $('#clone_url_id');
227 var $clone_by_name = $('#clone_by_name');
227 var $clone_by_name = $('#clone_by_name');
228 var $clone_by_id = $('#clone_by_id');
228 var $clone_by_id = $('#clone_by_id');
229 $clone_url.click(function(e){
229 $clone_url.click(function(e){
230 if($clone_url.hasClass('selected')){
230 if($clone_url.hasClass('selected')){
231 return ;
231 return ;
232 }else{
232 }else{
233 $clone_url.addClass('selected');
233 $clone_url.addClass('selected');
234 $clone_url.select();
234 $clone_url.select();
235 }
235 }
236 });
236 });
237
237
238 $clone_by_name.click(function(e){
238 $clone_by_name.click(function(e){
239 // show url by name and hide name button
239 // show url by name and hide name button
240 $clone_url.show();
240 $clone_url.show();
241 $clone_by_name.hide();
241 $clone_by_name.hide();
242
242
243 // hide url by id and show name button
243 // hide url by id and show name button
244 $clone_by_id.show();
244 $clone_by_id.show();
245 $clone_url_id.hide();
245 $clone_url_id.hide();
246 });
246 });
247
247
248 $clone_by_id.click(function(e){
248 $clone_by_id.click(function(e){
249 // show url by id and hide id button
249 // show url by id and hide id button
250 $clone_by_id.hide();
250 $clone_by_id.hide();
251 $clone_url_id.show();
251 $clone_url_id.show();
252
252
253 // hide url by name and show id button
253 // hide url by name and show id button
254 $clone_by_name.show();
254 $clone_by_name.show();
255 $clone_url.hide();
255 $clone_url.hide();
256 });
256 });
257
257
258 var cache = {}
258 var cache = {}
259 $("#download_options").select2({
259 $("#download_options").select2({
260 placeholder: _TM['Select changeset'],
260 placeholder: _TM['Select changeset'],
261 dropdownAutoWidth: true,
261 dropdownAutoWidth: true,
262 query: function(query){
262 query: function(query){
263 var key = 'cache';
263 var key = 'cache';
264 var cached = cache[key] ;
264 var cached = cache[key] ;
265 if(cached) {
265 if(cached) {
266 var data = {results: []};
266 var data = {results: []};
267 //filter results
267 //filter results
268 $.each(cached.results, function(){
268 $.each(cached.results, function(){
269 var section = this.text;
269 var section = this.text;
270 var children = [];
270 var children = [];
271 $.each(this.children, function(){
271 $.each(this.children, function(){
272 if(query.term.length == 0 || this.text.toUpperCase().indexOf(query.term.toUpperCase()) >= 0 ){
272 if(query.term.length == 0 || this.text.toUpperCase().indexOf(query.term.toUpperCase()) >= 0 ){
273 children.push({'id': this.id, 'text': this.text})
273 children.push({'id': this.id, 'text': this.text})
274 }
274 }
275 })
275 })
276 data.results.push({'text': section, 'children': children})
276 data.results.push({'text': section, 'children': children})
277 });
277 });
278 query.callback(data);
278 query.callback(data);
279 }else{
279 }else{
280 $.ajax({
280 $.ajax({
281 url: pyroutes.url('repo_refs_data', {'repo_name': '${c.repo_name}'}),
281 url: pyroutes.url('repo_refs_data', {'repo_name': '${c.repo_name}'}),
282 data: {},
282 data: {},
283 dataType: 'json',
283 dataType: 'json',
284 type: 'GET',
284 type: 'GET',
285 success: function(data) {
285 success: function(data) {
286 cache[key] = data;
286 cache[key] = data;
287 query.callback({results: data.results});
287 query.callback({results: data.results});
288 }
288 }
289 })
289 })
290 }
290 }
291 },
291 }
292 });
292 });
293 // on change of download options
293 // on change of download options
294 $('#download_options').change(function(e){
294 $('#download_options').change(function(e){
295 var new_cs = e.added
295 var new_cs = e.added
296
296
297 for(k in tmpl_links){
297 for(k in tmpl_links){
298 var s = $('#'+k+'_link');
298 var s = $('#'+k+'_link');
299 if(s){
299 if(s){
300 var title_tmpl = "${_('Download %s as %s') % ('__CS_NAME__','__CS_EXT__')}";
300 var title_tmpl = "${_('Download %s as %s') % ('__CS_NAME__','__CS_EXT__')}";
301 title_tmpl= title_tmpl.replace('__CS_NAME__',new_cs.text);
301 title_tmpl= title_tmpl.replace('__CS_NAME__',new_cs.text);
302 title_tmpl = title_tmpl.replace('__CS_EXT__',k);
302 title_tmpl = title_tmpl.replace('__CS_EXT__',k);
303 title_tmpl = '<i class="icon-archive"></i> '+ title_tmpl;
303 title_tmpl = '<i class="icon-archive"></i> '+ title_tmpl;
304 var url = tmpl_links[k].replace('__CS__',new_cs.id);
304 var url = tmpl_links[k].replace('__CS__',new_cs.id);
305 var subrepos = $('#archive_subrepos').is(':checked');
305 var subrepos = $('#archive_subrepos').is(':checked');
306 url = url.replace('__SUB__',subrepos);
306 url = url.replace('__SUB__',subrepos);
307 url = url.replace('__NAME__',title_tmpl);
307 url = url.replace('__NAME__',title_tmpl);
308
308
309 s.html(url)
309 s.html(url)
310 }
310 }
311 }
311 }
312 });
312 });
313
313
314 var tmpl_links = {};
314 var tmpl_links = {};
315 %for cnt,archive in enumerate(c.db_repo_scm_instance._get_archives()):
315 %for cnt,archive in enumerate(c.db_repo_scm_instance._get_archives()):
316 tmpl_links["${archive['type']}"] = '${h.link_to('__NAME__', h.url('files_archive_home',repo_name=c.db_repo.repo_name, fname='__CS__'+archive['extension'],subrepos='__SUB__'),class_='btn btn-small')}';
316 tmpl_links["${archive['type']}"] = '${h.link_to('__NAME__', h.url('files_archive_home',repo_name=c.db_repo.repo_name, fname='__CS__'+archive['extension'],subrepos='__SUB__'),class_='btn btn-small')}';
317 %endfor
317 %endfor
318 })
318 })
319 </script>
319 </script>
320
320
321 %if c.show_stats:
321 %if c.show_stats:
322 <script type="text/javascript">
322 <script type="text/javascript">
323 $(document).ready(function(){
323 $(document).ready(function(){
324 var data = ${c.trending_languages|n};
324 var data = ${c.trending_languages|n};
325 var total = 0;
325 var total = 0;
326 var no_data = true;
326 var no_data = true;
327 var tbl = document.createElement('table');
327 var tbl = document.createElement('table');
328 tbl.setAttribute('class','trending_language_tbl');
328 tbl.setAttribute('class','trending_language_tbl');
329 var cnt = 0;
329 var cnt = 0;
330 for (var i=0;i<data.length;i++){
330 for (var i=0;i<data.length;i++){
331 total+= data[i][1].count;
331 total+= data[i][1].count;
332 }
332 }
333 for (var i=0;i<data.length;i++){
333 for (var i=0;i<data.length;i++){
334 cnt += 1;
334 cnt += 1;
335 no_data = false;
335 no_data = false;
336
336
337 var hide = cnt>2;
337 var hide = cnt>2;
338 var tr = document.createElement('tr');
338 var tr = document.createElement('tr');
339 if (hide){
339 if (hide){
340 tr.setAttribute('style','display:none');
340 tr.setAttribute('style','display:none');
341 tr.setAttribute('class','stats_hidden');
341 tr.setAttribute('class','stats_hidden');
342 }
342 }
343 var k = data[i][0];
343 var k = data[i][0];
344 var obj = data[i][1];
344 var obj = data[i][1];
345 var percentage = Math.round((obj.count/total*100),2);
345 var percentage = Math.round((obj.count/total*100),2);
346
346
347 var td1 = document.createElement('td');
347 var td1 = document.createElement('td');
348 td1.width = 150;
348 td1.width = 150;
349 var trending_language_label = document.createElement('div');
349 var trending_language_label = document.createElement('div');
350 trending_language_label.innerHTML = obj.desc+" ("+k+")";
350 trending_language_label.innerHTML = obj.desc+" ("+k+")";
351 td1.appendChild(trending_language_label);
351 td1.appendChild(trending_language_label);
352
352
353 var td2 = document.createElement('td');
353 var td2 = document.createElement('td');
354 td2.setAttribute('style','padding-right:14px !important');
354 td2.setAttribute('style','padding-right:14px !important');
355 var trending_language = document.createElement('div');
355 var trending_language = document.createElement('div');
356 var nr_files = obj.count+" ${_('files')}";
356 var nr_files = obj.count+" ${_('files')}";
357
357
358 trending_language.title = k+" "+nr_files;
358 trending_language.title = k+" "+nr_files;
359
359
360 if (percentage>22){
360 if (percentage>22){
361 trending_language.innerHTML = "<b style='font-size:0.8em'>"+percentage+"% "+nr_files+ "</b>";
361 trending_language.innerHTML = "<b style='font-size:0.8em'>"+percentage+"% "+nr_files+ "</b>";
362 }
362 }
363 else{
363 else{
364 trending_language.innerHTML = "<b style='font-size:0.8em'>"+percentage+"%</b>";
364 trending_language.innerHTML = "<b style='font-size:0.8em'>"+percentage+"%</b>";
365 }
365 }
366
366
367 trending_language.setAttribute("class", 'trending_language top-right-rounded-corner bottom-right-rounded-corner');
367 trending_language.setAttribute("class", 'trending_language top-right-rounded-corner bottom-right-rounded-corner');
368 trending_language.style.width=percentage+"%";
368 trending_language.style.width=percentage+"%";
369 td2.appendChild(trending_language);
369 td2.appendChild(trending_language);
370
370
371 tr.appendChild(td1);
371 tr.appendChild(td1);
372 tr.appendChild(td2);
372 tr.appendChild(td2);
373 tbl.appendChild(tr);
373 tbl.appendChild(tr);
374 if(cnt == 3){
374 if(cnt == 3){
375 var show_more = document.createElement('tr');
375 var show_more = document.createElement('tr');
376 var td = document.createElement('td');
376 var td = document.createElement('td');
377 lnk = document.createElement('a');
377 lnk = document.createElement('a');
378
378
379 lnk.href='#';
379 lnk.href='#';
380 lnk.innerHTML = "${_('Show more')}";
380 lnk.innerHTML = "${_('Show more')}";
381 lnk.id='code_stats_show_more';
381 lnk.id='code_stats_show_more';
382 td.appendChild(lnk);
382 td.appendChild(lnk);
383
383
384 show_more.appendChild(td);
384 show_more.appendChild(td);
385 show_more.appendChild(document.createElement('td'));
385 show_more.appendChild(document.createElement('td'));
386 tbl.appendChild(show_more);
386 tbl.appendChild(show_more);
387 }
387 }
388
388
389 }
389 }
390
390
391 $('#lang_stats').appendChild(tbl);
391 $('#lang_stats').appendChild(tbl);
392 $('#code_status_show_more').click(function(){
392 $('#code_status_show_more').click(function(){
393 $('.stats_hidden').show();
393 $('.stats_hidden').show();
394 $('#code_status_show_more').hide();
394 $('#code_status_show_more').hide();
395 });
395 });
396 });
396 });
397 </script>
397 </script>
398 %endif
398 %endif
399
399
400 </%def>
400 </%def>
@@ -1,49 +1,49 b''
1 ## -*- coding: utf-8 -*-
1 ## -*- coding: utf-8 -*-
2 <li>
2 <li>
3 <a href="${h.url('branches_home',repo_name=c.repo_name)}" class="childs"><i class="icon-code-fork"></i> ${'%s (%s)' % (_('Branches'),len(c.db_repo_scm_instance.branches.values()),)}</a>
3 <a href="${h.url('branches_home',repo_name=c.repo_name)}" class="childs"><i class="icon-code-fork"></i> ${'%s (%s)' % (_('Branches'),len(c.db_repo_scm_instance.branches.values()))}</a>
4 <ul>
4 <ul>
5 %if c.db_repo_scm_instance.branches.values():
5 %if c.db_repo_scm_instance.branches.values():
6 %for cnt,branch in enumerate(c.db_repo_scm_instance.branches.items()):
6 %for cnt,branch in enumerate(c.db_repo_scm_instance.branches.items()):
7 <li><div><pre>${h.link_to('%s - %s' % (branch[0],h.short_id(branch[1])),h.url('files_home',repo_name=c.repo_name,revision=(branch[0] if '/' not in branch[0] else branch[1]), at=branch[0]))}</pre></div></li>
7 <li><div><pre>${h.link_to('%s - %s' % (branch[0],h.short_id(branch[1])),h.url('files_home',repo_name=c.repo_name,revision=(branch[0] if '/' not in branch[0] else branch[1]), at=branch[0]))}</pre></div></li>
8 %endfor
8 %endfor
9 %else:
9 %else:
10 <li>${h.link_to(_('There are no branches yet'),'#')}</li>
10 <li>${h.link_to(_('There are no branches yet'),'#')}</li>
11 %endif
11 %endif
12 </ul>
12 </ul>
13 </li>
13 </li>
14 %if c.db_repo_scm_instance.closed_branches.values():
14 %if c.db_repo_scm_instance.closed_branches.values():
15 <li>
15 <li>
16 <a href="${h.url('branches_home',repo_name=c.repo_name)}" class="childs"><i class="icon-code-fork"></i> ${'%s (%s)' % (_('Closed Branches'),len(c.db_repo_scm_instance.closed_branches.values()))}</a>
16 <a href="${h.url('branches_home',repo_name=c.repo_name)}" class="childs"><i class="icon-code-fork"></i> ${'%s (%s)' % (_('Closed Branches'),len(c.db_repo_scm_instance.closed_branches.values()))}</a>
17 <ul>
17 <ul>
18 %for cnt,branch in enumerate(c.db_repo_scm_instance.closed_branches.items()):
18 %for cnt,branch in enumerate(c.db_repo_scm_instance.closed_branches.items()):
19 <li><div><pre>${h.link_to('%s - %s' % (branch[0],h.short_id(branch[1])),h.url('files_home',repo_name=c.repo_name,revision=(branch[0] if '/' not in branch[0] else branch[1]), at=branch[0]))}</pre></div></li>
19 <li><div><pre>${h.link_to('%s - %s' % (branch[0],h.short_id(branch[1])),h.url('files_home',repo_name=c.repo_name,revision=(branch[0] if '/' not in branch[0] else branch[1]), at=branch[0]))}</pre></div></li>
20 %endfor
20 %endfor
21 </ul>
21 </ul>
22 </li>
22 </li>
23 %endif
23 %endif
24 <li>
24 <li>
25 <a href="${h.url('tags_home',repo_name=c.repo_name)}" class="childs"><i class="icon-tag"></i> ${'%s (%s)' % (_('Tags'),len(c.db_repo_scm_instance.tags.values()),)}</a>
25 <a href="${h.url('tags_home',repo_name=c.repo_name)}" class="childs"><i class="icon-tag"></i> ${'%s (%s)' % (_('Tags'),len(c.db_repo_scm_instance.tags.values()))}</a>
26 <ul>
26 <ul>
27 %if c.db_repo_scm_instance.tags.values():
27 %if c.db_repo_scm_instance.tags.values():
28 %for cnt,tag in enumerate(c.db_repo_scm_instance.tags.items()):
28 %for cnt,tag in enumerate(c.db_repo_scm_instance.tags.items()):
29 <li><div><pre>${h.link_to('%s - %s' % (tag[0],h.short_id(tag[1])),h.url('files_home',repo_name=c.repo_name,revision=(tag[0] if '/' not in tag[0] else tag[1]), at=tag[0]))}</pre></div></li>
29 <li><div><pre>${h.link_to('%s - %s' % (tag[0],h.short_id(tag[1])),h.url('files_home',repo_name=c.repo_name,revision=(tag[0] if '/' not in tag[0] else tag[1]), at=tag[0]))}</pre></div></li>
30 %endfor
30 %endfor
31 %else:
31 %else:
32 <li>${h.link_to(_('There are no tags yet'),'#')}</li>
32 <li>${h.link_to(_('There are no tags yet'),'#')}</li>
33 %endif
33 %endif
34 </ul>
34 </ul>
35 </li>
35 </li>
36 %if c.db_repo_scm_instance.alias == 'hg':
36 %if c.db_repo_scm_instance.alias == 'hg':
37 <li>
37 <li>
38 <a href="${h.url('bookmarks_home',repo_name=c.repo_name)}" class="childs"><i class="icon-bookmark"></i> ${'%s (%s)' % (_('Bookmarks'),len(c.db_repo_scm_instance.bookmarks.values()),)}</a>
38 <a href="${h.url('bookmarks_home',repo_name=c.repo_name)}" class="childs"><i class="icon-bookmark"></i> ${'%s (%s)' % (_('Bookmarks'),len(c.db_repo_scm_instance.bookmarks.values()))}</a>
39 <ul>
39 <ul>
40 %if c.db_repo_scm_instance.bookmarks.values():
40 %if c.db_repo_scm_instance.bookmarks.values():
41 %for cnt,book in enumerate(c.db_repo_scm_instance.bookmarks.items()):
41 %for cnt,book in enumerate(c.db_repo_scm_instance.bookmarks.items()):
42 <li><div><pre>${h.link_to('%s - %s' % (book[0],h.short_id(book[1])),h.url('files_home',repo_name=c.repo_name,revision=(book[0] if '/' not in book[0] else book[1]), at=book[0]))}</pre></div></li>
42 <li><div><pre>${h.link_to('%s - %s' % (book[0],h.short_id(book[1])),h.url('files_home',repo_name=c.repo_name,revision=(book[0] if '/' not in book[0] else book[1]), at=book[0]))}</pre></div></li>
43 %endfor
43 %endfor
44 %else:
44 %else:
45 <li>${h.link_to(_('There are no bookmarks yet'),'#')}</li>
45 <li>${h.link_to(_('There are no bookmarks yet'),'#')}</li>
46 %endif
46 %endif
47 </ul>
47 </ul>
48 </li>
48 </li>
49 %endif
49 %endif
@@ -1,97 +1,97 b''
1 ## -*- coding: utf-8 -*-
1 ## -*- coding: utf-8 -*-
2 <%inherit file="/base/base.html"/>
2 <%inherit file="/base/base.html"/>
3
3
4 <%def name="title()">
4 <%def name="title()">
5 ${_('%s Tags') % c.repo_name}
5 ${_('%s Tags') % c.repo_name}
6 %if c.site_name:
6 %if c.site_name:
7 &middot; ${c.site_name}
7 &middot; ${c.site_name}
8 %endif
8 %endif
9 </%def>
9 </%def>
10
10
11 <%def name="breadcrumbs_links()">
11 <%def name="breadcrumbs_links()">
12 <input class="q_filter_box" id="q_filter_tags" size="15" type="text" name="filter" placeholder="${_('quick filter...')}" value=""/>
12 <input class="q_filter_box" id="q_filter_tags" size="15" type="text" name="filter" placeholder="${_('quick filter...')}" value=""/>
13 ${_('Tags')}
13 ${_('Tags')}
14 </%def>
14 </%def>
15
15
16 <%def name="page_nav()">
16 <%def name="page_nav()">
17 ${self.menu('repositories')}
17 ${self.menu('repositories')}
18 </%def>
18 </%def>
19
19
20 <%def name="main()">
20 <%def name="main()">
21 ${self.repo_context_bar('switch-to')}
21 ${self.repo_context_bar('switch-to')}
22 <div class="box">
22 <div class="box">
23 <!-- box / title -->
23 <!-- box / title -->
24 <div class="title">
24 <div class="title">
25 ${self.breadcrumbs()}
25 ${self.breadcrumbs()}
26 </div>
26 </div>
27 <!-- end box / title -->
27 <!-- end box / title -->
28 %if c.repo_tags:
28 %if c.repo_tags:
29 <div class="info_box" id="compare_tags" style="clear: both;padding: 10px 19px;text-align: right;"><a href="#" class="btn btn-small">${_('Compare tags')}</a></div>
29 <div class="info_box" id="compare_tags" style="clear: both;padding: 10px 19px;text-align: right;"><a href="#" class="btn btn-small">${_('Compare tags')}</a></div>
30 %endif
30 %endif
31 <div class="table">
31 <div class="table">
32 <%include file='tags_data.html'/>
32 <%include file='tags_data.html'/>
33 </div>
33 </div>
34 </div>
34 </div>
35 <script type="text/javascript">
35 <script type="text/javascript">
36 $('#compare_tags').click(function(e){
36 $('#compare_tags').click(function(e){
37 e.preventDefault();
37 e.preventDefault();
38 var org = $('input[name=compare_org]:checked')[0];
38 var org = $('input[name=compare_org]:checked')[0];
39 var other = $('input[name=compare_other]:checked')[0];
39 var other = $('input[name=compare_other]:checked')[0];
40
40
41 if(org && other){
41 if(org && other){
42 var compare_url = "${h.url('compare_url',repo_name=c.repo_name,org_ref_type='tag',org_ref_name='__ORG__',other_ref_type='tag',other_ref_name='__OTHER__')}";
42 var compare_url = "${h.url('compare_url',repo_name=c.repo_name,org_ref_type='tag',org_ref_name='__ORG__',other_ref_type='tag',other_ref_name='__OTHER__')}";
43 var u = compare_url.replace('__ORG__',org.value)
43 var u = compare_url.replace('__ORG__',org.value)
44 .replace('__OTHER__',other.value);
44 .replace('__OTHER__',other.value);
45 window.location=u;
45 window.location=u;
46 }
46 }
47 });
47 });
48
48
49 // main table sorting
49 // main table sorting
50 var myColumnDefs = [
50 var myColumnDefs = [
51 {key:"name",label:"${_('Name')}",sortable:true,
51 {key:"name",label:"${_('Name')}",sortable:true,
52 sortOptions: { sortFunction: nameSort }},
52 sortOptions: { sortFunction: nameSort }},
53 {key:"date",label:"${_('Date')}",sortable:true,
53 {key:"date",label:"${_('Date')}",sortable:true,
54 sortOptions: { sortFunction: dateSort }},
54 sortOptions: { sortFunction: dateSort }},
55 {key:"author",label:"${_('Author')}",sortable:true},
55 {key:"author",label:"${_('Author')}",sortable:true},
56 {key:"revision",label:"${_('Revision')}",sortable:true,
56 {key:"revision",label:"${_('Revision')}",sortable:true,
57 sortOptions: { sortFunction: revisionSort }},
57 sortOptions: { sortFunction: revisionSort }},
58 {key:"compare",label:"${_('Compare')}",sortable:false,},
58 {key:"compare",label:"${_('Compare')}",sortable:false}
59 ];
59 ];
60
60
61 var myDataSource = new YAHOO.util.DataSource(YUD.get("tags_data"));
61 var myDataSource = new YAHOO.util.DataSource(YUD.get("tags_data"));
62
62
63 myDataSource.responseType = YAHOO.util.DataSource.TYPE_HTMLTABLE;
63 myDataSource.responseType = YAHOO.util.DataSource.TYPE_HTMLTABLE;
64
64
65 myDataSource.responseSchema = {
65 myDataSource.responseSchema = {
66 fields: [
66 fields: [
67 {key:"raw_name"},
67 {key:"raw_name"},
68 {key:"name"},
68 {key:"name"},
69 {key:"raw_date"},
69 {key:"raw_date"},
70 {key:"date"},
70 {key:"date"},
71 {key:"author"},
71 {key:"author"},
72 {key:"last_rev_raw"},
72 {key:"last_rev_raw"},
73 {key:"revision"},
73 {key:"revision"},
74 {key:"compare"},
74 {key:"compare"}
75 ]
75 ]
76 };
76 };
77
77
78 var myDataTable = new YAHOO.widget.DataTable("table_wrap", myColumnDefs, myDataSource,
78 var myDataTable = new YAHOO.widget.DataTable("table_wrap", myColumnDefs, myDataSource,
79 {
79 {
80 sortedBy:{key:"name",dir:"asc"},
80 sortedBy:{key:"name",dir:"asc"},
81 MSG_SORTASC:"${_('Click to sort ascending')}",
81 MSG_SORTASC:"${_('Click to sort ascending')}",
82 MSG_SORTDESC:"${_('Click to sort descending')}",
82 MSG_SORTDESC:"${_('Click to sort descending')}",
83 MSG_EMPTY:"${_('No records found.')}",
83 MSG_EMPTY:"${_('No records found.')}",
84 MSG_ERROR:"${_('Data error.')}",
84 MSG_ERROR:"${_('Data error.')}",
85 MSG_LOADING:"${_('Loading...')}",
85 MSG_LOADING:"${_('Loading...')}"
86 }
86 }
87 );
87 );
88 myDataTable.subscribe('postRenderEvent',function(oArgs) {
88 myDataTable.subscribe('postRenderEvent',function(oArgs) {
89 tooltip_activate();
89 tooltip_activate();
90 var func = function(node){
90 var func = function(node){
91 return node.parentNode.parentNode.parentNode.parentNode.parentNode;
91 return node.parentNode.parentNode.parentNode.parentNode.parentNode;
92 }
92 }
93 q_filter('q_filter_tags',YUQ('div.table tr td .logtags .tagtag a'),func);
93 q_filter('q_filter_tags',YUQ('div.table tr td .logtags .tagtag a'),func);
94 });
94 });
95
95
96 </script>
96 </script>
97 </%def>
97 </%def>
General Comments 0
You need to be logged in to leave comments. Login now