1
2jQuery(function(){
3
4	var request = {
5		trees : [],
6		links : [],
7		lists : []
8	};
9
10	jQuery('.bugzillalink').each(function( index, ele ){
11		request.links.push( jQuery(ele).data() );
12	});
13
14	jQuery('.bugzillatree').each(function( index, ele ){
15		request.trees.push( jQuery(ele).data() );
16	});
17
18	jQuery('.bugzillalist').each(function( index, ele ){
19		request.lists.push( jQuery(ele).data() );
20	});
21
22	if ( request.links.length + request.trees.length + request.lists.length > 0 ) {
23		fetchData( [{links:request.links}, {lists:request.lists}, {trees:request.trees}] );
24	}
25
26
27	function fetchData( requests ) {
28		var req = jQuery.extend( {call:'plugin_bugzillaint_fetch'}, requests.shift() );
29		jQuery.post( DOKU_BASE + 'lib/exe/ajax.php', req )
30		.done( handleData )
31		.done(function(){
32			if ( requests.length > 0 ) fetchData( requests );
33		})
34		.fail( handleError );
35	}
36
37	function handleError( a ) {
38		if ( a.readyState == 0 ) return;
39		var msg = a.status + " " + a.statusText + "\n\n" + a.responseText;
40		alert( msg );
41	}
42
43	function handleData( data ) {
44		if ( data.lists && data.lists.length > 0 ) {
45			jQuery('.bugzillalist').each(function( index, ele ){
46				var master = jQuery(ele).removeClass('loading');
47				var bugs = data.lists[index];
48				var groupBy = master.data('group_by');
49
50				master.toggleClass('empty', bugs.length == 0 );
51
52				for (var i=0, group=null; i < bugs.length; i++) {
53
54					if ( groupBy && group != bugs[i][groupBy] ) {
55						group = bugs[i][groupBy];
56						jQuery('<li class="group-headline"></li>')
57							.toggleClass('group-headline-first', i==0)
58							.append( ' – ' + group + ' – ' )
59							.appendTo( master.find('ul') );
60					}
61
62					jQuery('<li></li>')
63						.append( renderBug( master, bugs[i] ) )
64						.appendTo( master.find('ul') );
65				}
66			});
67		}
68		if ( data.links && jQuery.isEmptyObject(data.links) == false ) {
69			jQuery('.bugzillalink').each(function( index, ele ){
70				var master = jQuery(ele).removeClass('loading');
71				var bug = data.links[ master.data('id') ];
72				master.find('a.bzref').replaceWith( renderBug( master, bug ) );
73			});
74		}
75		if ( data.trees && jQuery.isEmptyObject(data.trees) == false ) {
76			jQuery('.bugzillatree').each(function( index, ele ){
77				var master = jQuery(ele).removeClass('loading');
78				var rootBug = data.trees[ master.data('id') ];
79				master.find('a.bzref').replaceWith( renderBug( master, rootBug ) );
80				renderTree( rootBug.depends_on, master.find('ul'), master, master.data('depth') );
81				master.toggleClass('empty', master.find('a.bzref').length <= 1 );
82			});
83		}
84	}
85
86
87	function renderBug( master, bug ) {
88
89		// bzref
90		var a = jQuery('<a></a>')
91			.addClass('bzref')
92			.attr('href', master.attr('bugzilla_baseurl') + '/show_bug.cgi?id=' + bug.id);
93		if ( bug.error ) {
94			a.addClass( 'bz-error' );
95			a.text( bug.id + ": " + bug.error );
96		} else {
97			if ( bug.resolution ) a.addClass( 'bz-resolved' );
98			a.text( bug.id + ": " + bug.summary );
99		}
100
101		// bzextra
102		var extra = renderExtras( master, bug );
103
104		return ( extra.children().length > 0 ) ? a.add( extra ) : a;
105	}
106
107
108	function renderExtras( master, bug ) {
109		var extras = master.data('extras').split(' ').join('').split(',');
110
111		// add properties with warnings to extras if they are not set
112		var warnings = getBugWarnings( master, bug );
113		for ( var property in warnings ) {
114			if ( extras.indexOf( property ) == -1 ) {
115				extras.unshift( property );
116			}
117		}
118
119		// render items
120		var bzextra = jQuery('<small class="bzextra"></span></small>');
121		jQuery.each( extras, function(index,val){
122			renderExtra( val, master, bzextra, bug );
123		});
124
125		return bzextra;
126	}
127
128
129	function renderExtra( extra, master, parent, bug ) {
130
131		var groupBy = master.data('group_by');
132		var e;
133
134		if ( extra == 'assigned_to' && groupBy != 'assigned_to' ) {
135			e = jQuery('<a></a>');
136			e.attr('href', master.attr('bugzilla_baseurl') + '/buglist.cgi?bug_status=NEW&bug_status=ASSIGNED&bug_status=REOPENED&emailassigned_to1=1&emailtype1=substring&query_format=advanced&email1=' + encodeURIComponent(bug.assigned_to) );
137			e.attr('title', 'assigned to ' + bug.assigned_to);
138			e.append( bug.assigned_to );
139		}
140
141		if ( extra == 'classification' && groupBy != 'classification' ) {
142			e = jQuery('<a></a>');
143			e.attr('href', master.attr('bugzilla_baseurl') + '/buglist.cgi?bug_status=NEW&bug_status=ASSIGNED&bug_status=REOPENED&query_format=advanced&classification=' + encodeURIComponent(bug.classification) );
144			e.attr('title', 'Classification: ' + bug.classification);
145			e.append( bug.classification );
146		}
147
148		if ( extra == 'product' && groupBy != 'product' ) {
149			e = jQuery('<a></a>');
150			e.attr('href', master.attr('bugzilla_baseurl') + '/describecomponents.cgi?product=' + encodeURIComponent(bug.product) );
151			e.attr('title', 'Product: ' + bug.product);
152			e.append( bug.product );
153		}
154
155		if ( extra == 'component' && groupBy != 'component' ) {
156			e = jQuery('<a></a>');
157			e.attr('href', master.attr('bugzilla_baseurl') + '/buglist.cgi?resolution=---&component=' + encodeURIComponent(bug.component) + (bug.product?'&product='+encodeURIComponent(bug.product):'') );
158			e.attr('title', 'Component: ' + bug.component);
159			e.append( bug.product );
160		}
161
162		if ( extra == 'lastchange' && groupBy != 'last_change_time' && bug.last_change_time ) {
163			e = jQuery('<span title ></span>');
164			e.attr('title', 'last changed on ' + bug.last_change_time);
165			e.append( "MOD " + bug.last_change_time );
166		}
167
168		if ( extra == 'time' && bug.actual_time && bug.actual_time > 0 ) {
169			e = jQuery('<span></span>');
170			e.attr('title', 'actual time taken ' + bug.actual_time);
171			e.append( "" + bug.actual_time + "h" );
172		}
173
174		if ( extra == 'deadline' && bug.deadline ) {
175			e = jQuery('<span></span>');
176			e.attr('title', 'deadline: ' + bug.deadline);
177			e.append( 'DL ' + bug.deadline );
178		}
179
180		if ( extra == 'priority' && groupBy != 'priority' ) {
181			e = jQuery('<span></span>');
182			e.attr('title', 'priority: ' + bug.priority);
183			e.append( bug.priority );
184		}
185
186		if ( extra == 'severity' && groupBy != 'severity' ) {
187			e = jQuery('<span></span>');
188			e.attr('title', 'severity: ' + bug.severity);
189			e.append( bug.severity );
190		}
191
192		if ( extra == 'version' && groupBy != 'version' && bug.version && bug.version != 'unspecified' ) {
193			e = jQuery('<span></span>');
194			e.append( bug.version );
195		}
196
197		if ( extra == 'status' && groupBy != 'status' ) {
198			e = jQuery('<span></span>');
199			if ( bug.resolution ) {
200				e.attr('title', 'status: ' + bug.status + ' / ' + bug.resolution );
201				e.addClass('bz-label-' + master.attr( 'color_resolved_' + bug.resolution.toLowerCase() ) );
202				e.append(bug.resolution);
203			} else {
204				e.addClass('bz-label-' + master.attr( 'color_' + bug.status.toLowerCase() ) );
205				e.append( bug.status );
206			}
207		}
208
209		if ( extra == 'dependencies' ) {
210			e = jQuery('<a></a>')
211				.attr('href', master.attr('bugzilla_baseurl') + '/showdependencytree.cgi?hide_resolved=0&id=' + bug.id);
212			if (bug.depends_on_resolved && bug.depends_on_resolved.length < bug.depends_on.length) {
213				e.append(
214					master.attr('extra_depends_on').split('{0}').join(bug.depends_on.length - bug.depends_on_resolved.length)
215				);
216			}
217			if (bug.blocks_resolved && bug.blocks_resolved.length < bug.blocks.length) {
218				if (e.text().length > 0) {
219					e.append(', ');
220				}
221				e.append(
222					master.attr('extra_blocks').split('{0}').join(bug.blocks.length - bug.blocks_resolved.length)
223				);
224			}
225		}
226
227		if ( e && e.text().length > 0 ) {
228
229			// check if warning exists
230			var warnings = getBugWarnings( master, bug );
231			if ( warnings.hasOwnProperty(extra) ) {
232				e.addClass('bz-label-' + warnings[extra].color );
233			}
234
235			// add extra to parent
236			parent.append( e );
237		}
238
239	}
240
241
242
243	function renderTree( bugs, parent, master, depth ) {
244
245		// exit if depth is extended
246		if ( depth-- < 1 ) return;
247
248		// created sorted array of bugs
249		var l = [];
250		for (var k in bugs) {
251			l.push( bugs[k] );
252		}
253		l.sort(function(a,b){
254			if ( parseInt(a.id) < parseInt(b.id) ) return -1;
255			if ( parseInt(a.id) < parseInt(b.id) ) return 1;
256			return 0;
257		});
258
259		for (var i=0; i < l.length; i++) {
260			var bug = l[i];
261
262			if ( master.data('hideresolved') && bug.status == "RESOLVED" ) continue;
263
264			var li = jQuery('<li></li>')
265				.append( renderBug( master, bug ) )
266				.appendTo( parent );
267
268			if ( jQuery.isEmptyObject( bug.depends_on ) == false ) {
269				var ul = jQuery('<ul></ul>').appendTo( li );
270				renderTree( bug.depends_on, ul, master, depth );
271			}
272
273		}
274	}
275
276
277	function getBugWarnings( master, bug ) {
278
279		if ( bug.hasOwnProperty('warnings') ) {
280			return bug.warnings;
281		}
282
283		bug.warnings = {};
284
285		if ( !bug.resolution && bug.severity ) {
286			var red = master.attr('severity_threshold_red');
287			var orange = master.attr('severity_threshold_orange');
288
289			var s = ['blocker', 'major', 'normal', 'minor', 'enhancement'];
290			if ( s.indexOf(bug.severity) <= s.indexOf(red) ) {
291				bug.warnings.severity = { color:'red', property:'severity' };
292			} else if ( s.indexOf(bug.severity) <= s.indexOf(orange) ) {
293				bug.warnings.severity = { color:'orange', property:'severity' };
294			}
295		}
296
297		if ( !bug.resolution && bug.priority ) {
298			var red = master.attr('priority_threshold_red');
299			var orange = master.attr('priority_threshold_orange');
300
301			var p = parseInt(bug.priority.split('P')[1]);
302			var r = parseInt(red.split('P')[1]);
303			var o = parseInt(orange.split('P')[1]);
304			if ( p <= r ) {
305				bug.warnings.priority = { color:'red', property:'priority' };
306			} else if ( p <= o ) {
307				bug.warnings.priority = { color:'orange', property:'priority' };
308			}
309		}
310
311		if ( !bug.resolution && bug.deadline ) {
312			var red = master.attr('deadline_threshold_days_red');
313			var orange = master.attr('deadline_threshold_days_orange');
314
315			var p = bug.deadline.split('-');
316			var deadlineTime = new Date(p[0], p[1]-1, p[2], 0, 0, 0, 0).getTime();
317			var nowTime = new Date().getTime();
318			if ( nowTime > deadlineTime - (red*24*60*60*1000) ) {
319				bug.warnings.deadline = { color:'red', property:'deadline' };
320			} else if ( nowTime > deadlineTime - (orange*24*60*60*1000) ) {
321				bug.warnings.deadline = { color:'orange', property:'deadline' };
322			}
323		}
324
325		return bug.warnings;
326	}
327
328
329});
330