window.widget_svggraph_form = new class { init({form_tabs_id, color_palette, templateid}) { colorPalette.setThemeColors(color_palette); this._$overlay_body = jQuery('.overlay-dialogue-body'); this._form = document.getElementById('widget-dialogue-form'); this._templateid = templateid; this._dataset_wrapper = document.getElementById('data_sets'); this._$overlay_body.on('scroll', () => { const $preview = jQuery('.', this._$overlay_body); if (!$preview.length) { this._$overlay_body.off('scroll'); return; } if ($preview.offset().top < this._$overlay_body.offset().top && this._$overlay_body.height() > 400) { jQuery('#svg-graph-preview').css('top', this._$overlay_body.offset().top - $preview.offset().top ); jQuery('.graph-widget-config-tabs .ui-tabs-nav').css('top', $preview.height()); } else { jQuery('#svg-graph-preview').css('top', 0); jQuery('.graph-widget-config-tabs .ui-tabs-nav').css('top', 0); } }); jQuery(`#${form_tabs_id}`) .on('tabsactivate', () => jQuery.colorpicker('hide')) .on('change', 'input, z-select, .multiselect', (e) => this.onGraphConfigChange(e)); this._datasetTabInit(); this._timePeriodTabInit(); this._legendTabInit(); this._problemsTabInit(); this.onGraphConfigChange(); } onGraphConfigChange() { this._updateForm(); this._updatePreview(); } updateVariableOrder(obj, row_selector, var_prefix) { for (const k of [10000, 0]) { jQuery(row_selector, obj).each(function(i) { if (var_prefix === 'ds') { jQuery(this).attr('data-set', i); jQuery('.single-item-table', this).attr('data-set', i); } jQuery('.multiselect[data-params]', this).each(function() { const name = jQuery(this).multiSelect('getOption', 'name'); if (name !== null) { jQuery(this).multiSelect('modify', { name: name.replace(/([a-z]+\[)\d+(]\[[a-z_]+])/, `$1${k + i}$2`) }); } }); jQuery(`[name^="${var_prefix}["]`, this) .filter(function () { return jQuery(this).attr('name').match(/[a-z]+\[\d+]\[[a-z_]+]/); }) .each(function () { jQuery(this).attr('name', jQuery(this).attr('name').replace(/([a-z]+\[)\d+(]\[[a-z_]+])/, `$1${k + i}$2`) ); }); }); } } _datasetTabInit() { this._updateDatasetsLabel(); // Initialize vertical accordion. jQuery(this._dataset_wrapper) .on('focus', '. input.input', function() { jQuery('#data_sets').zbx_vertical_accordion('expandNth', jQuery(this).closest('.').index() ); }) .on('click', function(e) { if (!e.target.classList.contains('color-picker-preview')) { jQuery.colorpicker('hide'); } if (e.target.classList.contains('js-click-expend') || e.target.classList.contains('color-picker-preview') || e.target.classList.contains('')) { jQuery('#data_sets').zbx_vertical_accordion('expandNth', jQuery(e.target).closest('.').index() ); } }) .on('collapse', function(event, data) { jQuery('textarea, .multiselect', data.section).scrollTop(0); jQuery(window).trigger('resize'); const dataset = data.section[0]; if (dataset.dataset.type == '') { const message_block = dataset.querySelector('.no-items-message'); if (dataset.querySelectorAll('.single-item-table-row').length == 0) { message_block.style.display = 'block'; } } }) .on('expand', function(event, data) { jQuery(window).trigger('resize'); const dataset = data.section[0]; if (dataset.dataset.type == '') { const message_block = dataset.querySelector('.no-items-message'); if (dataset.querySelectorAll('.single-item-table-row').length == 0) { message_block.style.display = 'none'; } widget_svggraph_form._initSingleItemSortable(dataset); } }) .zbx_vertical_accordion({handler: '.'}); // Initialize rangeControl UI elements. jQuery('.', jQuery(this._dataset_wrapper)).rangeControl(); // Initialize pattern fields. jQuery('.multiselect', jQuery(this._dataset_wrapper)).each(function() { jQuery(this).multiSelect(jQuery(this).data('params')); }); for (const colorpicker of jQuery('. input')) { jQuery(colorpicker).colorpicker({ onUpdate: function(color) { jQuery('.', jQuery(this).closest('.') ).css('background-color', `#${color}`); }, appendTo: '.overlay-dialogue-body' }); } this._dataset_wrapper.addEventListener('click', (e) => { if (e.target.classList.contains('js-add')) { this._selectItems(); } if (e.target.classList.contains('element-table-remove')) { this._removeSingleItem(e.target); } if (e.target.classList.contains('js-remove')) { this._removeDataSet(e.target); } }); document .getElementById('dataset-add') .addEventListener('click', () => { this._addDataset(); }); document .getElementById('dataset-menu') .addEventListener('click', (e) => this._addDatasetMenu(e)); window.addPopupValues = (list) => { if (!isset('object', list) || list.object !== 'itemid') { return false; } for (let i = 0; i < list.values.length; i++) { this._addSingleItem(list.values[i].itemid, list.values[i].name); } this._updateSingleItemsLinks(); this._initSingleItemSortable(this._getOpenedDataset()); this._updatePreview(); } this._updateSingleItemsLinks(); this._initDataSetSortable(); this._initSingleItemSortable(this._getOpenedDataset()); } _timePeriodTabInit() { document.getElementById('graph_time') .addEventListener('click', (e) => { document.getElementById('time_from').disabled = !e.target.checked; document.getElementById('time_to').disabled = !e.target.checked; document.getElementById('time_from_calendar').disabled = !e.target.checked; document.getElementById('time_to_calendar').disabled = !e.target.checked; }); } _legendTabInit() { document.getElementById('legend') .addEventListener('click', (e) => { jQuery('#legend_lines').rangeControl( e.target.checked ? 'enable' : 'disable' ); if (!e.target.checked) { jQuery('#legend_columns').rangeControl('disable'); } else if (!document.getElementById('legend_statistic').checked) { jQuery('#legend_columns').rangeControl('enable'); } document.getElementById('legend_statistic').disabled = !e.target.checked; }); document.getElementById('legend_statistic') .addEventListener('click', (e) => { jQuery('#legend_columns').rangeControl( !e.target.checked ? 'enable' : 'disable' ); }); } _problemsTabInit() { const widget = document.getElementById('problems'); document.getElementById('show_problems') .addEventListener('click', (e) => { jQuery('#graph_item_problems, #problem_name, #problemhosts_select').prop('disabled', !e.target.checked); jQuery('#problemhosts_').multiSelect(e.target.checked ? 'enable' : 'disable'); jQuery('[name^="severities["]', jQuery(widget)).prop('disabled', !e.target.checked); jQuery('[name="evaltype"]', jQuery(widget)).prop('disabled', !e.target.checked); jQuery('input, button, z-select', jQuery('#tags_table_tags', jQuery(widget))).prop('disabled', !e.target.checked ); }); } _updateDatasetsLabel() { for (const dataset of this._dataset_wrapper.querySelectorAll('.')) { this._updateDatasetLabel(dataset); } } _updateDatasetLabel(dataset) { const placeholder_text = + ` #${parseInt(dataset.dataset.set) + 1}`; const data_set_label = dataset.querySelector('.js-dataset-label'); const data_set_label_input = dataset.querySelector(`[name="ds[${dataset.dataset.set}][data_set_label]"]`); data_set_label.textContent = data_set_label_input.value !== '' ? data_set_label_input.value : placeholder_text; data_set_label_input.placeholder = placeholder_text; } _addDatasetMenu(e) { const menu = [ { items: [ { label: , clickCallback: () => { this._addDataset(); } }, { label: , clickCallback: () => { this._addDataset(); } } ] }, { items: [ { label: , disabled: this._getOpenedDataset() === null, clickCallback: () => { this._cloneDataset(); } } ] } ]; jQuery(e.target).menuPopup(menu, new jQuery.Event(e), { position: { of: e.target, my: 'left top', at: 'left bottom', within: '.wrapper' } }); } _addDataset(type) { jQuery(this._dataset_wrapper).zbx_vertical_accordion('collapseAll'); const template = type == ? new Template(jQuery('#dataset-single-item-tmpl').html()) : new Template(jQuery('#dataset-pattern-item-tmpl').html()); const used_colors = []; for (const color of this._form.querySelectorAll('. input')) { if (color.value !== '') { used_colors.push(color.value); } } this._dataset_wrapper.insertAdjacentHTML('beforeend', template.evaluate({ rowNum: this._dataset_wrapper.querySelectorAll('.').length, color: type == ? '' : colorPalette.getNextColor(used_colors) })); const dataset = this._getOpenedDataset(); for (const colorpicker of dataset.querySelectorAll('. input')) { jQuery(colorpicker).colorpicker({appendTo: '.overlay-dialogue-body'}); } for (const multiselect of dataset.querySelectorAll('.multiselect')) { jQuery(multiselect).multiSelect(jQuery(multiselect).data('params')); } for (const range_control of dataset.querySelectorAll('.')) { jQuery(range_control).rangeControl(); } this._$overlay_body.scrollTop(Math.max(this._$overlay_body.scrollTop(), this._form.scrollHeight - this._$overlay_body.height() )); this._initDataSetSortable(); this._updateForm(); } _cloneDataset() { const dataset = this._getOpenedDataset(); this._addDataset(dataset.dataset.type); const cloned_dataset = this._getOpenedDataset(); if (dataset.dataset.type == ) { for (const row of dataset.querySelectorAll('.single-item-table-row')) { this._addSingleItem( row.querySelector(`[name^='ds[${dataset.getAttribute('data-set')}][itemids]`).value, row.querySelector('.table-col-name a').textContent ); } this._updateSingleItemsLinks(); this._initSingleItemSortable(cloned_dataset); } else { if (this._templateid === null) { jQuery('.js-hosts-multiselect', cloned_dataset).multiSelect('addData', jQuery('.js-hosts-multiselect', dataset).multiSelect('getData') ); } jQuery('.js-items-multiselect', cloned_dataset).multiSelect('addData', jQuery('.js-items-multiselect', dataset).multiSelect('getData') ); } for (const input of dataset.querySelectorAll('[name^=ds]')) { const cloned_name = input.name.replace(/([a-z]+\[)\d+(]\[[a-z_]+])/, `$1${cloned_dataset.getAttribute('data-set')}$2` ); if (input.tagName.toLowerCase() === 'z-select') { cloned_dataset.querySelector(`[name="${cloned_name}"]`).value = input.value; } else if (input.type === 'text') { cloned_dataset.querySelector(`[name="${cloned_name}"]`).value = input.value; if (input.classList.contains('')) { // Fire change event to redraw range input. cloned_dataset.querySelector(`[name="${cloned_name}"]`).dispatchEvent(new Event('change')); } } else if (input.type === 'checkbox' || input.type === 'radio') { // Click to fire events. cloned_dataset.querySelector(`[name="${cloned_name}"][value="${input.value}"]`).checked = input.checked; } } this._updateDatasetLabel(cloned_dataset); this._updatePreview(); } _removeDataSet(obj) { obj .closest('.list-accordion-item') .remove(); this.updateVariableOrder(jQuery(this._dataset_wrapper), '.', 'ds'); this._updateDatasetsLabel(); const dataset = this._getOpenedDataset(); if (dataset !== null) { this._updateSingleItemsOrder(dataset); this._initSingleItemSortable(dataset); } this._initDataSetSortable(); this._updateSingleItemsLinks(); this.onGraphConfigChange(); } _getOpenedDataset() { return this._dataset_wrapper.querySelector('.[data-set]'); } _initDataSetSortable() { const datasets_count = this._dataset_wrapper.querySelectorAll('.').length; for (const drag_icon of this._dataset_wrapper.querySelectorAll('.js-main-drag-icon')) { drag_icon.classList.toggle('disabled', datasets_count < 2); } if (this._sortable_data_set === undefined) { this._sortable_data_set = new CSortable( document.querySelector('#data_set .'), {is_vertical: true} ); this._sortable_data_set.on(SORTABLE_EVENT_DRAG_END, () => { this.updateVariableOrder(this._dataset_wrapper, '.', 'ds'); this._updateDatasetsLabel(); this._updatePreview(); }); } this._sortable_data_set.enableSorting(datasets_count > 1); } _selectItems() { if (this._templateid === null) { PopUp('popup.generic', { srctbl: 'items', srcfld1: 'itemid', srcfld2: 'name', dstfrm: this._form.id, numeric: 1, writeonly: 1, multiselect: 1, with_webitems: 1, real_hosts: 1 }); } else { PopUp('popup.generic', { srctbl: 'items', srcfld1: 'itemid', srcfld2: 'name', dstfrm: this._form.id, numeric: 1, writeonly: 1, multiselect: 1, with_webitems: 1, hostid: this._templateid, hide_host_filter: 1 }); } } _addSingleItem(itemid, name) { const dataset = this._getOpenedDataset(); const items_table = dataset.querySelector('.single-item-table'); if (items_table.querySelector(`input[value="${itemid}"]`) !== null) { return; } const dataset_index = dataset.getAttribute('data-set'); const template = new Template(jQuery('#dataset-item-row-tmpl').html()); const item_next_index = items_table.querySelectorAll('.single-item-table-row').length + 1; items_table.querySelector('tbody').insertAdjacentHTML('beforeend', template.evaluate({ dsNum: dataset_index, rowNum: item_next_index, name: name, itemid: itemid })); const used_colors = []; for (const color of this._form.querySelectorAll('. input')) { if (color.value !== '') { used_colors.push(color.value); } } jQuery(`#items_${dataset_index}_${item_next_index}_color`) .val(colorPalette.getNextColor(used_colors)) .colorpicker(); } _removeSingleItem(element) { element.closest('.single-item-table-row').remove(); const dataset = this._getOpenedDataset(); this._updateSingleItemsOrder(dataset); this._updateSingleItemsLinks(); this._initSingleItemSortable(dataset); this._updatePreview(); } _initSingleItemSortable(dataset) { const item_rows = dataset.querySelectorAll('.single-item-table-row'); if (item_rows.length < 1) { return; } for (const row of item_rows) { row.querySelector('.').classList.toggle('disabled', item_rows.length < 2); } jQuery(`.single-item-table`, dataset).sortable({ disabled: item_rows.length < 2, items: '.single-item-table-row', axis: 'y', containment: 'parent', cursor: 'grabbing', handle: '.', tolerance: 'pointer', opacity: 0.6, update: () => { this._updateSingleItemsOrder(dataset); this._updateSingleItemsLinks(); }, helper: (e, ui) => { for (const td of ui.find('>td')) { const $td = jQuery(td); $td.attr('width', $td.width()); } // When dragging element on safari, it jumps out of the table. if (SF) { // Move back draggable element to proper position. ui.css('left', (ui.offset().left - 2) + 'px'); } return ui; }, stop: (e, ui) => { ui.item.find('>td').removeAttr('width'); }, start: (e, ui) => { jQuery(ui.placeholder).height(jQuery(ui.helper).height()); } }); } _updateSingleItemsLinks() { for (const dataset of this._dataset_wrapper.querySelectorAll('.')) { const dataset_index = dataset.getAttribute('data-set'); const size = dataset.querySelectorAll('.single-item-table-row').length + 1; for (let i = 0; i < size; i++) { jQuery(`#items_${dataset_index}_${i}_name`).off('click').on('click', () => { let ids = []; for (let i = 0; i < size; i++) { ids.push(jQuery(`#items_${dataset_index}_${i}_input`).val()); } if (this._templateid === null) { PopUp('popup.generic', { srctbl: 'items', srcfld1: 'itemid', srcfld2: 'name', dstfrm: widget_svggraph_form._form.id, dstfld1: `items_${dataset_index}_${i}_input`, dstfld2: `items_${dataset_index}_${i}_name`, numeric: 1, writeonly: 1, with_webitems: 1, real_hosts: 1, dialogue_class: 'modal-popup-generic', excludeids: ids }); } else { PopUp('popup.generic', { srctbl: 'items', srcfld1: 'itemid', srcfld2: 'name', dstfrm: widget_svggraph_form._form.id, dstfld1: `items_${dataset_index}_${i}_input`, dstfld2: `items_${dataset_index}_${i}_name`, numeric: 1, writeonly: 1, with_webitems: 1, hostid: this._templateid, hide_host_filter: 1, dialogue_class: 'modal-popup-generic', excludeids: ids }); } }); } } } _updateSingleItemsOrder(dataset) { jQuery.colorpicker('destroy', jQuery('.single-item-table . input', dataset)); const dataset_index = dataset.getAttribute('data-set'); for (const row of dataset.querySelectorAll('.single-item-table-row')) { const prefix = `items_${dataset_index}_${row.rowIndex}`; row.querySelector('.table-col-no span').textContent = `${row.rowIndex}:`; row.querySelector('.table-col-name a').id = `${prefix}_name`; row.querySelector('.table-col-action input').id = `${prefix}_input`; const colorpicker = row.querySelector('.single-item-table . input'); colorpicker.id = `${prefix}_color`; jQuery(colorpicker).colorpicker({appendTo: '.overlay-dialogue-body'}); } } _updateForm() { const axes_used = {: 0, : 0}; for (const element of this._form.querySelectorAll('[type=radio], [type=hidden]')) { if (element.name.match(/ds\[\d+]\[axisy]/) && element.checked) { axes_used[element.value]++; } } for (const element of this._form.querySelectorAll('[type=hidden]')) { if (element.name.match(/or\[\d+]\[axisy]/)) { axes_used[element.value]++; } } const dataset = this._getOpenedDataset(); if (dataset !== null) { this._updateDatasetLabel(dataset); const dataset_index = dataset.getAttribute('data-set'); const draw_type = dataset.querySelector(`[name="ds[${dataset_index}][type]"]:checked`); const is_stacked = dataset.querySelector(`[type=checkbox][name="ds[${dataset_index}][stacked]"]`).checked; // Data set tab. const aggregate_function_select = dataset.querySelector(`[name="ds[${dataset_index}][aggregate_function]"]`); const approximation_select = dataset.querySelector(`[name="ds[${dataset_index}][approximation]"]`); let stacked_enabled = true; let width_enabled = true; let pointsize_enabled = true; let fill_enabled = true; let missingdata_enabled = true; let aggregate_none_enabled = true; let approximation_all_enabled = true; switch (draw_type.value) { case '': pointsize_enabled = false; if (is_stacked) { approximation_all_enabled = false; } break; case '': stacked_enabled = false; width_enabled = false; fill_enabled = false; missingdata_enabled = false; approximation_all_enabled = false; break; case '': pointsize_enabled = false; approximation_all_enabled = false; break; case '': width_enabled = false; pointsize_enabled = false; fill_enabled = false; missingdata_enabled = false; if (is_stacked) { aggregate_none_enabled = false; } approximation_all_enabled = false; break; } dataset.querySelector(`[type=checkbox][name="ds[${dataset_index}][stacked]"]`).disabled = !stacked_enabled; jQuery(`[name="ds[${dataset_index}][width]"]`, dataset).rangeControl(width_enabled ? 'enable' : 'disable'); jQuery(`[name="ds[${dataset_index}][pointsize]"]`, dataset).rangeControl( pointsize_enabled ? 'enable' : 'disable' ); jQuery(`[name="ds[${dataset_index}][fill]"]`, dataset).rangeControl(fill_enabled ? 'enable' : 'disable'); for (const element of dataset.querySelectorAll(`[name="ds[${dataset_index}][missingdatafunc]"]`)) { element.disabled = !missingdata_enabled; } aggregate_function_select.getOptionByValue().disabled = !aggregate_none_enabled; if (!aggregate_none_enabled && aggregate_function_select.value == ) { aggregate_function_select.value = ; } const aggregation_enabled = aggregate_function_select.value != ; dataset.querySelector(`[name="ds[${dataset_index}][aggregate_interval]"]`).disabled = !aggregation_enabled; for (const element of dataset.querySelectorAll(`[name="ds[${dataset_index}][aggregate_grouping]"]`)) { element.disabled = !aggregation_enabled; } approximation_select.getOptionByValue().disabled = !approximation_all_enabled; if (!approximation_all_enabled && approximation_select.value == ) { approximation_select.value = ; } } // Displaying options tab. const percentile_left_checkbox = document.getElementById('percentile_left'); percentile_left_checkbox.disabled = !axes_used[]; document.getElementById('percentile_left_value').disabled = !percentile_left_checkbox.checked || !axes_used[]; const percentile_right_checkbox = document.getElementById('percentile_right'); percentile_right_checkbox.disabled = !axes_used[]; document.getElementById('percentile_right_value').disabled = !percentile_right_checkbox.checked || !axes_used[]; // Axes tab. const lefty_checkbox = document.getElementById('lefty'); lefty_checkbox.disabled = !axes_used[]; const lefty_on = !lefty_checkbox.disabled && lefty_checkbox.checked; if (lefty_checkbox.disabled) { lefty_checkbox.checked = true; } for (const element of document.querySelectorAll('#lefty_min, #lefty_max, #lefty_units')) { element.disabled = !lefty_on; } document.getElementById('lefty_static_units').disabled = !lefty_on || document.getElementById('lefty_units').value != ; const righty_checkbox = document.getElementById('righty'); righty_checkbox.disabled = !axes_used[]; const righty_on = !righty_checkbox.disabled && righty_checkbox.checked; if (righty_checkbox.disabled) { righty_checkbox.checked = true; } for (const element of document.querySelectorAll('#righty_min, #righty_max, #righty_units')) { element.disabled = !righty_on; } document.getElementById('righty_static_units').disabled = !righty_on || document.getElementById('righty_units').value != ; // Trigger event to update tab indicators. document.getElementById('tabs').dispatchEvent(new Event(TAB_INDICATOR_UPDATE_EVENT)); } _updatePreview() { // Update graph preview. const $preview = jQuery('#svg-graph-preview'); const $preview_container = $preview.parent(); const preview_data = $preview_container.data(); const $form = jQuery(this._form); const url = new Curl('zabbix.php'); const data = { uniqueid: 0, preview: 1, contents_width: Math.floor($preview.width()), contents_height: Math.floor($preview.height()) - 10 }; url.setArgument('action', 'widget.svggraph.view'); const form_fields = $form.serializeJSON(); if ('ds' in form_fields) { for (const i in form_fields.ds) { form_fields.ds[i] = jQuery.extend({'hosts': [], 'items': []}, form_fields.ds[i]); } } if ('or' in form_fields) { for (const i in form_fields.or) { form_fields.or[i] = jQuery.extend({'hosts': [], 'items': []}, form_fields.or[i]); } } data.fields = form_fields; if (this._templateid !== null) { data.templateid = this._templateid } if (preview_data.xhr) { preview_data.xhr.abort(); } if (preview_data.timeoutid) { clearTimeout(preview_data.timeoutid); } preview_data.timeoutid = setTimeout(function() { $preview_container.addClass('is-loading'); }, 1000); preview_data.xhr = jQuery.ajax({ url: url.getUrl(), method: 'POST', contentType: 'application/json', data: JSON.stringify(data), dataType: 'json', success: function(r) { if (preview_data.timeoutid) { clearTimeout(preview_data.timeoutid); } $preview_container.removeClass('is-loading'); $form.prev('.msg-bad').remove(); if ('error' in r) { const message_box = makeMessageBox('bad', r.error.messages, r.error.title); message_box.insertBefore($form); } if (typeof r.body !== 'undefined') { $preview.html(jQuery(r.body)).attr('unselectable', 'on').css('user-select', 'none'); } } }); $preview_container.data(preview_data); } };