1 var invalid_report_names
= '';
3 var sla_month_error_color
= 'red';
4 var sla_month_disabled_color
= '#cdcdcd';
5 var sla_month_enabled_color
= '#fafafa';
6 var nr_of_scheduled_instances
= 0;
7 var current_obj_type
= false; // keep track of what we are viewing
8 $(document
).ready(function() {
9 // handle the move-between-lists-button (> + <) and double click events
10 function move_right() {
11 var selects
= $(this).parent().parent().find('select');
12 moveAndSort(selects
.filter(':first'), selects
.filter(':last'));
14 function move_left() {
15 var selects
= $(this).parent().parent().find('select');
16 moveAndSort(selects
.filter(':last'), selects
.filter(':first'));
18 $('.arrow-right').click(move_right
);
19 $('.arrow-left').click(move_left
);
20 $('#hostgroup_tmp, #servicegroup_tmp, #host_tmp, #service_tmp, #objects_tmp').dblclick(move_right
);
21 $('#hostgroup, #servicegroup, #host_name, #service_description, #objects').dblclick(move_left
);
23 $("#hide_response").click(function() {
27 $(".fancybox").fancybox({
28 'overlayOpacity' : 0.7,
29 'overlayColor' : '#ffffff',
30 'hideOnContentClick' : false,
32 'autoDimensions': true,
36 $('#filter_field').keyup(function() {
37 if ($(this).attr('value') == '') {
38 MyRegexp
.resetFilter($("select[id$=_tmp]").filter(":visible").attr('id'));
41 MyRegexp
.selectFilter($("select[id$=_tmp]").filter(":visible").attr('id'), this.value
);
44 $('#clear_filter').click(function() {
45 $('#filter_field').attr('value', '');
46 MyRegexp
.resetFilter($("select[id$=_tmp]").filter(":visible").attr('id'));
47 $('#filter_field').focus();
50 var direct_link_visible
= false;
51 $('#current_report_params').click(function() {
52 // make sure we always empty the field
53 $('#link_container').html('');
54 // .html('<form><input type="text" size="200" value="' + $('#current_report_params').attr('href') + '"></form>')
55 if (!direct_link_visible
) {
57 .html('<form>'+_label_direct_link
+' <input class="wide" type="text" value="'
58 + document
.location
.protocol
+ '//'
59 + document
.location
.host
60 + $('#current_report_params').attr('href')
62 .css('position', 'absolute')
63 .css('top', this.offsetHeight
+ this.offsetTop
+ 5)
66 direct_link_visible
= true;
68 $('#link_container').hide();
69 direct_link_visible
= false;
74 $('#save_report').click(function() {
75 if (!direct_link_visible
) {
76 $('#save_report_form')
77 .css('position', 'absolute')
78 .css('top', this.offsetHeight
+ this.offsetTop
+ 5)
81 .find('input[name=report_name]')
84 if(input
.value
== "") {
88 direct_link_visible
= true;
90 $('#save_report_form').hide();
91 direct_link_visible
= false;
96 $("#report_id").bind('change', function() {
97 $("#saved_report_form").trigger('submit');
100 $('.save_report_btn').parents('form').submit(function(ev
) {
104 if (!(check_form_values(this[0]))) {
107 var btn
= form
.find('.save_report_btn');
111 type
: form
[0].method
,
112 data
: form
.serialize(),
113 complete: function() {
114 btn
.parent().find('img:last').remove();
116 success: function(data
, status_msg
, xhr
) {
118 $.notify(_reports_error
+ ": " + xhr
.responseText
, {'sticky': true});
121 jgrowl_message(data
.status_msg
, _reports_success
);
122 if (!btn
[0].form
.report_id
)
123 $('form').append('<input type="hidden" name="report_id" value="'+data
.report_id
+'"/>');
125 $('#save_report_form').hide();
127 error: function(data
) {
128 $.notify(_reports_error
+ ": " + data
.responseText
, {'sticky': true});
129 btn
.parent().find('img:last').remove();
135 $('select[name=report_type]').on('change', function() {
136 var value
= this.value
;
137 set_selection(value
);
138 get_members(value
, function(all_names
) {
139 populate_options($('#objects_tmp'), $('#objects'), all_names
);
142 var value
= this.value
;
143 set_selection(value
);
144 get_members(value
, function(all_names
) {
145 populate_options($('#objects_tmp'), $(), all_names
);
146 var tmp
= $('#objects_tmp');
147 var mo
= new missing_objects();
148 var elems
= $('#objects').children();
149 for (var i
= 0; i
< elems
.length
; i
++) {
151 if (tmp
.containsOption(prop
.value
))
152 tmp
.removeOption(prop
.value
);
159 $('#sel_report_type').on('click', function() {
160 var value
= this.form
.report_type
.value
;
161 set_selection(value
);
162 get_members(value
, function(all_names
) {
163 populate_options($('#objects_tmp'), $('#objects'), all_names
);
168 var start_date
= new Date(0);
169 var end_date
= new Date();
171 url
: _site_domain
+ _index_page
+ '/sla/custom_start/',
174 success: function(data
) {
175 start_date
.setTime(data
.timestamp
* 1000);
176 var html
= '<option></option>';
177 for (i
= start_date
.getFullYear(); i
<= end_date
.getFullYear(); i
++) {
178 html
+= '<option>' + i
+ '</option>';
180 $('#start_year').html(html
);
181 $('#end_year').html(html
);
184 $('#start_year, #end_year').on('change', function () {
187 if (this.value
== start_date
.getFullYear()) {
188 start
= start_date
.getMonth();
190 if (this.value
== end_date
.getFullYear()) {
191 end
= end_date
.getMonth();
193 var html
= '<option></option>';
194 for (i
= start
; i
<= end
; i
++) {
195 html
+= '<option value="' + (i
+1) + '">' + Date
.monthNames
[i
] + '</option>';
197 if (this.id
== 'start_year')
198 $('#start_month').html(html
);
200 $('#end_month').html(html
);
203 $('#start_year, #end_year, #start_month, #end_month').on('change', check_custom_months
);
204 $("#delete_report").click(confirm_delete_report
);
206 $(".report_form").on('submit', function() {
208 return check_form_values();
212 var loadimg
= new Image(16,16);
213 loadimg
.src
= _site_domain
+ 'application/media/images/loading_small.gif';
215 function init_datepicker()
217 // datePicker Jquery plugin
218 var datepicker_enddate
= (new Date()).asString();
219 $('.date-pick').datePicker({clickInput
:true, startDate
:_start_date
, endDate
:datepicker_enddate
});
222 function(e
, selectedDates
)
224 var d
= selectedDates
[0];
227 $('#cal_end').dpSetStartDate(d
.asString());
233 function(e
, selectedDates
)
235 var d
= selectedDates
[0];
238 $('#cal_start').dpSetEndDate(d
.asString());
244 function show_hide(id
,h1
) {
245 if ($('#' + id
) && !$('#' + id
).is(':visible')) {
248 .css('background', 'url(icons/arrows/grey-down.gif) 7px 7px no-repeat');
252 .css('background', 'url(icons/arrows/grey.gif) 11px 3px no-repeat');
256 function show_calendar(val
, update
) {
258 $("#custom_time").show();
264 $('input[name=start_time]').attr('value', '');
265 $('input[name=end_time]').attr('value', '');
268 $("#custom_time").hide();
270 disable_sla_fields(val
);
273 function set_selection(val
) {
274 if ($.inArray(val
, ['servicegroups', 'hostgroups', 'services', 'hosts']) === -1)
275 val
= 'hostgroups'; // Why? Because I found it like this
276 $('.object-list-type').text(val
);
277 $('*[data-show-for]').hide()
278 $('*[data-show-for~='+val
+']').show()
281 function get_members(type
, cb
) {
284 var field_name
= false;
285 var empty_field
= false;
287 show_progress('progress', _wait_str
);
289 url
: _site_domain
+ _index_page
+ '/ajax/group_member',
291 error: function(data
) {
292 $.notify("Unable to fetch objects: " + data
.responseText
, {'sticky': true});
294 success: function(all_names
) {
295 if(typeof cb
== 'function')
297 $('#progress').css('display', 'none');
304 * Fetch the report periods for selected report type.
306 * Result will be returned to populate_report_periods() below.
308 function get_report_periods(type
)
310 var ajax_url
= _site_domain
+ _index_page
+ '/ajax/';
311 var url
= ajax_url
+ "get_report_periods/";
312 var data
= {type
: type
};
313 $('#report_period').empty();
314 set_selected_period(type
);
320 success: function(data
) {
323 populate_report_periods(data
);
326 $.notify(_reports_error
+ ": Unable to fetch report periods", {'sticky': true});
333 * Populate HTML select list with supplied JSON data
335 function populate_options(tmp_field
, field
, json_data
)
339 show_progress('progress', _wait_str
);
340 var available
= document
.createDocumentFragment();
341 var selected
= document
.createDocumentFragment();
342 for (i
= 0; i
< (json_data
? json_data
.length
: 0); i
++) {
343 var option
= document
.createElement("option");
344 option
.appendChild(document
.createTextNode(json_data
[i
]));
345 available
.appendChild(option
);
347 tmp_field
.append(available
);
348 field
.append(selected
);
352 * Re-populate report_period select field
354 function populate_report_periods(json_data
)
356 var field_name
= 'report_period';
357 for (var i
= 0; i
< json_data
.length
; i
++) {
358 var val
= json_data
[i
].optionValue
;
359 var txt
= json_data
[i
].optionText
;
360 $("#" + field_name
).addOption(val
, txt
, false);
362 disable_sla_fields($('#report_period option:selected').val());
363 setTimeout('delayed_hide_progress()', 1000);
367 * Set selected report period to default
368 * (and disable sla fields out of scope if sla)
370 function set_selected_period(val
)
372 $("#report_period").selectOptions(val
);
373 disable_sla_fields(val
);
376 // delay hiding of progress indicator
377 function delayed_hide_progress()
379 setup_hide_content('progress');
382 function setup_hide_content(d
) {
389 function hide_response() {setup_hide_content('response');}
391 function toggle_field_visibility(val
, theId
) {
393 $('#' + theId
).show();
395 $('#' + theId
).hide();
400 * Loop through all elements of a form
401 * Verify that all multiselect fields (right hand side)
402 * are set to selected
404 function loopElements(f
) {
405 // select all elements that doesn't contain the nosave_suffix
406 $('.multiple:not([id$=_tmp])').each(function() {
407 if ($(this).is(':visible')) {
408 $(this).children('option').attr('selected', 'selected');
410 $(this).children('option').attr('selected', false);
415 function check_form_values(form
)
418 form
= document
.documentElement
;
424 var rpt_type
= $("select[name=report_type]", form
).val();
425 if ($("#report_period", form
).val() == 'custom') {
426 if ($('input[name=type]', form
).val() != 'sla') {
428 cur_start
= Date
.fromString($("input[name=cal_start]", form
).val());
429 var time
= $(".time_start", form
).val().split(':');
430 cur_start
.addHours(time
[0]);
431 cur_start
.addMinutes(time
[1]);
432 cur_end
= Date
.fromString($("input[name=cal_end]", form
).val());
433 time
= $(".time_end", form
).val().split(':');
434 cur_end
.addHours(time
[0]);
435 cur_end
.addMinutes(time
[1]);
436 var now
= new Date();
437 if (!cur_start
|| !cur_end
) {
440 err_str
+= "<li>" + _reports_invalid_startdate
+ ".</li>";
444 err_str
+= "<li>" + _reports_invalid_enddate
+ ".</li>";
448 if (!confirm(_reports_enddate_infuture
)) {
456 if (cur_end
< cur_start
) {
458 err_str
+= "<li>" + _reports_enddate_lessthan_startdate
+ ".</li>";
459 $(".datepick-start", form
).addClass("time_error");
460 $(".datepick-end", form
).addClass("time_error");
462 $(".datepick-start", form
).removeClass("time_error");
463 $(".datepick-end", form
).removeClass("time_error");
466 // verify that we have years and month fields
467 if ($('#start_year', form
).val() == '' || $('#start_month', form
).val() == ''
468 || $('#end_year', form
).val() == '' || $('#end_month', form
).val() == '') {
470 //@@@Fixme: Add translated string
471 err_str
+= "<li>Please select year and month for both start and end. ";
472 err_str
+= "<br />Please note that SLA reports can only be generated for previous months</li>";
475 // remember: our months are 1-indexed
476 cur_start
= new Date(0);
477 cur_start
.setYear($("select[name=start_year]", form
).val());
478 cur_start
.addMonths(Number($("select[name=start_month]", form
).val()) - 1);
480 cur_end
= new Date(0);
481 cur_end
.setYear($("select[name=end_year]", form
).val());
482 cur_end
.addMonths(Number($("select[name=end_month]", form
).val()));
485 if (cur_end
< cur_start
) {
487 err_str
+= "<li>" + _reports_enddate_lessthan_startdate
+ ".</li>";
488 $(".datepick-start", form
).addClass("time_error");
489 $(".datepick-end", form
).addClass("time_error");
491 $(".datepick-start", form
).removeClass("time_error");
492 $(".datepick-end", form
).removeClass("time_error");
497 if ($('input[name=report_mode]:checked', form
).val() != 'standard' && !$('#show_all', form
).is(':checked') && $("#objects", form
).is('select') && $('#objects option', form
).length
== 0) {
499 err_str
+= "<li>" + _reports_err_str_noobjects
+ ".</li>";
502 if ($("#enter_sla", form
).is(":visible")) {
503 // check for sane SLA values
504 var red_error
= false;
508 for (i
=1;i
<=12;i
++) {
509 var field_name
= 'month_' + i
;
510 var input
= $('input[id="' + field_name
+ '"]', form
);
511 var value
= input
.attr('value');
512 value
= value
.replace(',', '.');
513 if (value
> max_val
|| isNaN(value
)) {
514 input
.css('background', sla_month_error_color
);
521 if (input
.attr('disabled'))
522 input
.css('background', sla_month_disabled_color
);
524 input
.css('background', sla_month_enabled_color
);
528 err_str
+= '<li>' + _reports_sla_err_str
+ '</li>';
531 if (nr_of_slas
== 0 && !red_error
) {
533 err_str
+= "<li>" + _reports_no_sla_str
+ "</li>";
537 // create array prototype to sole the lack of in_array() in javascript
538 Array
.prototype.has = function(value
) {
540 for (var i
= 0, loopCnt
= this.length
; i
< loopCnt
; i
++) {
541 if (this[i
] === value
) {
548 var report_name
= $("input[name=report_name]", form
).attr('value');
549 report_name
= $.trim(report_name
);
550 var saved_report_id
= $("input[name=saved_report_id]", form
).attr('value');
551 var do_save_report
= $('input[name=save_report_settings]', form
).is(':checked') ? 1 : 0;
554 * Only perform checks if:
555 * - Saved report exists
556 * - User checked the 'Save Report' checkbox
557 * - We are currently editing a report (i.e. have saved_report_id)
559 if ($('#report_id', form
) && do_save_report
&& saved_report_id
) {
560 // Saved reports exists
561 $('#report_id option', form
).each(function(i
) {
562 if ($(this).val()) {// first item is empty
563 if (saved_report_id
!= $(this).val()) {
564 // check all the other saved reports
565 // make sure we don't miss the scheduled reports
566 var chk_text
= $(this).text();
567 chk_text
= chk_text
.replace(" ( *" + _scheduled_label
+ "* )", '');
568 if (report_name
== chk_text
) {
569 // trying to save an item with an existing name
571 err_str
+= "<li>" + _reports_error_name_exists
+ ".</li>";
577 } else if (do_save_report
&& report_name
== '') {
578 // trying to save a report without a name
580 err_str
+= "<li>" + _reports_name_empty
+ "</li>";
583 // display err_str if any
585 $('#response', form
).html('');
587 // check if report name is unique
588 if(report_name
&& saved_report_id
== '' && invalid_report_names
&& invalid_report_names
.has(report_name
))
590 if(!confirm(_reports_error_name_exists_replace
))
596 $('#response', form
).hide();
600 // clear all style info from progress
601 var resp
= $('#response', form
);
603 resp
= $('#response');
604 resp
.attr("style", "");
605 resp
.html("<ul class='alert error'>" + err_str
+ "</ul>");
606 window
.scrollTo(0,0); // make sure user sees the error message
610 function epoch_to_human(val
){
611 var the_date
= new Date(val
* 1000);
615 function hideMe(elem
)
617 $('#' + elem
).hide('slow');
620 function show_message(class_name
, msg
) {
621 $('#response').show().html('<ul class="' + class_name
+ '">' + msg
+ '<br /></ul>');
622 setTimeout('hide_response()', 5000);
625 function moveAndSort(from, to
)
627 from.find('option:selected').remove().appendTo(to
);
631 // init timepicker once it it is shown
632 function init_timepicker()
634 $("#time_start, #time_end").timePicker();
637 function disable_sla_fields(report_period
)
639 if (!$('#month_1').length
)
641 var now
= new Date();
642 var this_month
= now
.getMonth()+1;
643 switch (report_period
) {
645 // weird as it seems, the following call actually ENABLES
646 // all months. If not, we could end up with all months being
647 // disabled for 'thisyear'
648 disable_months(0, 12);
649 for (i
=this_month
+ 1;i
<=12;i
++)
651 $('.report_form #month_' + i
).val('').attr('disabled', true).css('background-color', sla_month_disabled_color
);
655 check_custom_months();
658 disable_last_months(1);
661 disable_last_months(3);
664 disable_last_months(6);
668 disable_months(0, 12);
674 } else if (this_month
<= 6) {
677 } else if (this_month
<= 9){
684 disable_months(from, to
);
689 $('#month_' + i
).attr('disabled', false).css('bgcolor', sla_month_enabled_color
);
695 function disable_months(start
, end
)
697 var disabled_state
= false;
698 var not_disabled_state
= false;
700 start
= Number(start
);
702 for (i
=1;i
<=12;i
++) {
703 var cell
= $('.report_form #month_' + i
);
705 if ( i
>= start
|| i
<= end
) {
706 cell
.attr('disabled', false).css('background-color', sla_month_enabled_color
);
708 cell
.val('').attr('disabled', true).css('background-color', sla_month_disabled_color
);
711 if ( i
>= start
&& i
<= end
) {
712 cell
.attr('disabled', false).css('background-color', sla_month_enabled_color
);
714 cell
.val('').attr('disabled', true).css('background-color', sla_month_disabled_color
);
721 function check_custom_months()
723 var f
= $('.report_form').get(0);
725 if (!f
['start_month'])
727 var start_year
= f
.start_year
.value
;
728 var start_month
= f
.start_month
.value
;
729 var end_year
= f
.end_year
.value
;
730 var end_month
= f
.end_month
.value
;
731 if (start_year
!='' && end_year
!='' && start_month
!='' && end_month
!='') {
732 if (start_year
< end_year
) {
733 // start and end months will have to "restart"
734 disable_months(start_month
, end_month
);
736 if (start_year
< end_year
|| start_year
== end_year
) {
737 // simple case - disable from start_month to end_month
738 disable_months(start_month
, end_month
);
740 // start_year > end_year = ERROR
741 // handled by check_form_values but let's disable all months?
742 disable_months(0, 0);
746 setTimeout('check_custom_months()', 1000);
748 setup_hide_content('progress');
752 * Generic function to disable month_ fields
753 * depending on if selection is last 1, 3 or 6 months.
755 function disable_last_months(mnr
)
757 var now
= new Date();
758 var this_month
= now
.getMonth()+1;
761 var from = (this_month
-mnr
);
762 var to
= (this_month
-1);
763 from = from<=0 ? (from + 12) : from;
764 to
= to
<=0 ? (to
+ 12) : to
;
765 disable_months(from, to
);
768 function missing_objects()
773 missing_objects
.prototype.add = function(name
)
776 this.objs
.push(name
);
779 missing_objects
.prototype.display_if_any = function()
781 if (!this.objs
.length
)
784 var info_str
= _reports_missing_objects
+ ": ";
785 info_str
+= "<ul><li><img src=\"" + _site_domain
+ "application/views/icons/arrow-right.gif" + "\" /> " + this.objs
.join('</li><li><img src="' + _site_domain
+ 'application/views/icons/arrow-right.gif' + '" /> ') + '</li></ul>';
786 info_str
+= _reports_missing_objects_pleaseremove
;
787 info_str
+= '<a href="#" id="hide_response" onclick="hideMe(\'response\')" style="position:absolute;top:8px;left:700px;">Close <img src="' + _site_domain
+ '' + 'application/views/icons/12x12/cross.gif" /></a>';
789 .css('background','#f4f4ed url(' + _site_domain
+ 'application/views/icons/32x32/shield-info.png) 7px 7px no-repeat')
790 .css("position", "relative")
792 .css('width','748px')
794 .css('padding','15px 2px 5px 50px')
795 .css('margin-left','5px')
799 function confirm_delete_report()
802 var id
= $("#report_id").attr('value')
804 var is_scheduled
= $('#is_scheduled').text()!='' ? true : false;
805 var msg
= _reports_confirm_delete
+ "\n";
806 var type
= $('input[name=type]').attr('value');
810 msg
+= _reports_confirm_delete_warning
;
812 msg
= msg
.replace("this saved report", "the saved report '"+$('#report_id option[selected=selected]').text()+"'");
816 url
: _site_domain
+ _index_page
+ '/' + _controller_name
+ '/delete/',
819 success: function(data
) {
820 var a
= document
.createElement("a");
821 a
.href
= window
.location
.href
;
822 if(a
.search
&& a
.search
.indexOf("report_id="+id
) !== -1) {
823 window
.location
.href
= a
.search
.replace(new RegExp("report_id="+id
+"&?"), "");
827 $.notify(_reports_error
+ ": failed to save report.", {'sticky': true});
836 regex: function(a
, i
, m
, r
) {
837 var r
= new RegExp(m
[3], 'i');
838 return r
.test(jQuery(a
).text());
844 * Regexp filter that (hopefully) works for all browsers
847 function init_regexpfilter() {
848 MyRegexp
= new Object();
849 MyRegexp
.selectFilterData
= new Object();
850 MyRegexp
.selectFilter = function(selectId
, filter
) {
851 var list
= document
.getElementById(selectId
);
852 if(!MyRegexp
.selectFilterData
[selectId
]) {
853 //if we don't have a list of all the options, cache them now'
854 MyRegexp
.selectFilterData
[selectId
] = new Array();
855 for(var i
= 0; i
< list
.options
.length
; i
++)
856 MyRegexp
.selectFilterData
[selectId
][i
] = list
.options
[i
];
858 list
.options
.length
= 0; //remove all elements from the list
859 var r
= new RegExp(filter
, 'i');
860 for(var i
= 0; i
< MyRegexp
.selectFilterData
[selectId
].length
; i
++) {
861 //add elements from cache if they match filter
862 var o
= MyRegexp
.selectFilterData
[selectId
][i
];
863 //if(o.text.toLowerCase().indexOf(filter.toLowerCase()) >= 0) list.add(o, null);
864 if(!o
.parentNode
&& r
.test(o
.text
)) list
.add(o
, null);
867 MyRegexp
.resetFilter = function(selectId
) {
868 if (typeof MyRegexp
.selectFilterData
[selectId
] == 'undefined' || !MyRegexp
.selectFilterData
[selectId
].length
)
870 var list
= document
.getElementById(selectId
);
871 list
.options
.length
= 0; //remove all elements from the list
872 for(var i
= 0; i
< MyRegexp
.selectFilterData
[selectId
].length
; i
++) {
873 //add elements from cache if they match filter
874 var o
= MyRegexp
.selectFilterData
[selectId
][i
];