Merge branch 'ent-11423-nueva-herramienta-graph-analytics' into 'develop'
Ent 11423 nueva herramienta graph analytics See merge request artica/pandorafms!6327
This commit is contained in:
commit
6102cb5015
|
@ -1,5 +1,13 @@
|
|||
START TRANSACTION;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `tgraph_analytics_filter` (
|
||||
`id` INT NOT NULL auto_increment,
|
||||
`filter_name` VARCHAR(45) NULL,
|
||||
`user_id` VARCHAR(255) NULL,
|
||||
`graph_modules` TEXT NULL,
|
||||
`interval` INT NULL,
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=UTF8MB4;
|
||||
|
||||
UPDATE `twelcome_tip`
|
||||
SET title = 'Scheduled downtimes',
|
||||
|
|
File diff suppressed because one or more lines are too long
After Width: | Height: | Size: 22 KiB |
|
@ -807,6 +807,7 @@ define('AUDIT_LOG_FILE_MANAGER', 'File manager');
|
|||
define('AUDIT_LOG_ALERT_MANAGEMENT', 'Alert management');
|
||||
define('AUDIT_LOG_ALERT_CORRELATION_MANAGEMENT', 'Alert correlation management');
|
||||
define('AUDIT_LOG_VISUAL_CONSOLE_MANAGEMENT', 'Visual Console Management');
|
||||
define('AUDIT_LOG_GRAPH_ANALYTICS_PUBLIC', 'Graph Analytics Public');
|
||||
define('AUDIT_LOG_TAG_MANAGEMENT', 'Tag management');
|
||||
define('AUDIT_LOG_SNMP_MANAGEMENT', 'SNMP management');
|
||||
define('AUDIT_LOG_DASHBOARD_MANAGEMENT', 'Dashboard management');
|
||||
|
|
|
@ -270,7 +270,8 @@ function format_for_graph(
|
|||
$dec_point='.',
|
||||
$thousands_sep=',',
|
||||
$divider=1000,
|
||||
$sufix=''
|
||||
$sufix='',
|
||||
$two_lines=false
|
||||
) {
|
||||
// Exception to exclude modules whose unit is already formatted as KB (satellite modules)
|
||||
if (!empty($sufix) && $sufix == 'KB') {
|
||||
|
@ -297,6 +298,10 @@ function format_for_graph(
|
|||
}
|
||||
|
||||
// This will actually do the rounding and the decimals.
|
||||
if ($two_lines === true) {
|
||||
return remove_right_zeros(format_numeric($number, $decimals)).'<br>'.$shorts[$pos].$sufix;
|
||||
}
|
||||
|
||||
return remove_right_zeros(format_numeric($number, $decimals)).$shorts[$pos].$sufix;
|
||||
}
|
||||
|
||||
|
@ -4046,25 +4051,49 @@ function series_type_graph_array($data, $show_elements_graph)
|
|||
}
|
||||
} else {
|
||||
$name_legend = '';
|
||||
if (isset($show_elements_graph['fullscale']) === true
|
||||
&& (int) $show_elements_graph['fullscale'] === 1
|
||||
) {
|
||||
$name_legend .= 'Tip: ';
|
||||
} else {
|
||||
$name_legend .= 'Avg: ';
|
||||
}
|
||||
|
||||
if ($value['unit']) {
|
||||
$name_legend .= $value['agent_alias'];
|
||||
$name_legend .= ' / ';
|
||||
$name_legend .= $value['module_name'];
|
||||
$name_legend .= ' / ';
|
||||
$name_legend .= __('Unit ').' ';
|
||||
$name_legend .= $value['unit'].': ';
|
||||
if ($show_elements_graph['graph_analytics'] === true) {
|
||||
$name_legend .= '<div class="graph-analytics-legend-main">';
|
||||
$name_legend .= '<div class="graph-analytics-legend-square" style="background-color: '.$color_series[$i]['color'].';">';
|
||||
$name_legend .= '<span class="square-value">';
|
||||
$name_legend .= format_for_graph(
|
||||
end(end($value['data'])),
|
||||
1,
|
||||
$config['decimal_separator'],
|
||||
$config['thousand_separator'],
|
||||
1000,
|
||||
'',
|
||||
true
|
||||
);
|
||||
$name_legend .= '</span>';
|
||||
$name_legend .= '<span class="square-unit" title="'.$value['unit'].'">'.$value['unit'].'</span>';
|
||||
$name_legend .= '</div>';
|
||||
$name_legend .= '<div class="graph-analytics-legend">';
|
||||
$name_legend .= '<span>'.$value['agent_alias'].'</span>';
|
||||
$name_legend .= '<span title="'.$value['module_name'].'">'.$value['module_name'].'</span>';
|
||||
$name_legend .= '</div>';
|
||||
$name_legend .= '</div>';
|
||||
} else {
|
||||
$name_legend .= $value['agent_alias'];
|
||||
$name_legend .= ' / ';
|
||||
$name_legend .= $value['module_name'].': ';
|
||||
if (isset($show_elements_graph['fullscale']) === true
|
||||
&& (int) $show_elements_graph['fullscale'] === 1
|
||||
) {
|
||||
$name_legend .= 'Tip: ';
|
||||
} else {
|
||||
$name_legend .= 'Avg: ';
|
||||
}
|
||||
|
||||
if ($value['unit']) {
|
||||
$name_legend .= $value['agent_alias'];
|
||||
$name_legend .= ' / ';
|
||||
$name_legend .= $value['module_name'];
|
||||
$name_legend .= ' / ';
|
||||
$name_legend .= __('Unit ').' ';
|
||||
$name_legend .= $value['unit'].': ';
|
||||
} else {
|
||||
$name_legend .= $value['agent_alias'];
|
||||
$name_legend .= ' / ';
|
||||
$name_legend .= $value['module_name'].': ';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -4085,28 +4114,30 @@ function series_type_graph_array($data, $show_elements_graph)
|
|||
$value['max'] = 0;
|
||||
}
|
||||
|
||||
$data_return['legend'][$key] .= '<span class="legend-font-small">'.__('Min').' </span><span class="bolder">'.remove_right_zeros(
|
||||
number_format(
|
||||
$value['min'],
|
||||
$config['graph_precision'],
|
||||
$config['csv_decimal_separator'],
|
||||
$config['csv_decimal_separator'] == ',' ? '.' : ','
|
||||
)
|
||||
).' '.$value['unit'].'</span> <span class="legend-font-small">'.__('Max').' </span><span class="bolder">'.remove_right_zeros(
|
||||
number_format(
|
||||
$value['max'],
|
||||
$config['graph_precision'],
|
||||
$config['csv_decimal_separator'],
|
||||
$config['csv_decimal_separator'] == ',' ? '.' : ','
|
||||
)
|
||||
).' '.$value['unit'].'</span> <span class="legend-font-small">'._('Avg.').' </span><span class="bolder">'.remove_right_zeros(
|
||||
number_format(
|
||||
$value['avg'],
|
||||
$config['graph_precision'],
|
||||
$config['csv_decimal_separator'],
|
||||
$config['csv_decimal_separator'] == ',' ? '.' : ','
|
||||
)
|
||||
).' '.$value['unit'].'</span> '.$str;
|
||||
if (isset($show_elements_graph['graph_analytics']) === false) {
|
||||
$data_return['legend'][$key] .= '<span class="legend-font-small">'.__('Min').' </span><span class="bolder">'.remove_right_zeros(
|
||||
number_format(
|
||||
$value['min'],
|
||||
$config['graph_precision'],
|
||||
$config['csv_decimal_separator'],
|
||||
$config['csv_decimal_separator'] == ',' ? '.' : ','
|
||||
)
|
||||
).' '.$value['unit'].'</span> <span class="legend-font-small">'.__('Max').' </span><span class="bolder">'.remove_right_zeros(
|
||||
number_format(
|
||||
$value['max'],
|
||||
$config['graph_precision'],
|
||||
$config['csv_decimal_separator'],
|
||||
$config['csv_decimal_separator'] == ',' ? '.' : ','
|
||||
)
|
||||
).' '.$value['unit'].'</span> <span class="legend-font-small">'._('Avg.').' </span><span class="bolder">'.remove_right_zeros(
|
||||
number_format(
|
||||
$value['avg'],
|
||||
$config['graph_precision'],
|
||||
$config['csv_decimal_separator'],
|
||||
$config['csv_decimal_separator'] == ',' ? '.' : ','
|
||||
)
|
||||
).' '.$value['unit'].'</span> '.$str;
|
||||
}
|
||||
|
||||
if ($show_elements_graph['compare'] == 'overlapped'
|
||||
&& $key == 'sum2'
|
||||
|
|
|
@ -5540,3 +5540,23 @@ function graph_events_agent_by_group($id_group, $width=300, $height=200, $noWate
|
|||
$options
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
function graph_analytics_filter_select()
|
||||
{
|
||||
global $config;
|
||||
|
||||
$result = [];
|
||||
|
||||
if (check_acl($config['id_user'], 0, 'RW') === 1 || check_acl($config['id_user'], 0, 'RM') === 1) {
|
||||
$filters = db_get_all_rows_sql('SELECT id, filter_name FROM tgraph_analytics_filter WHERE user_id = "'.$config['id_user'].'"');
|
||||
|
||||
if ($filters !== false) {
|
||||
foreach ($filters as $filter) {
|
||||
$result[$filter['id']] = $filter['filter_name'];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
|
|
@ -4511,7 +4511,8 @@ function ui_toggle(
|
|||
$switch_on=null,
|
||||
$switch_name=null,
|
||||
$disableToggle=false,
|
||||
$id_table=false
|
||||
$id_table=false,
|
||||
$position_tgl_div=false
|
||||
) {
|
||||
// Generate unique Id.
|
||||
$uniqid = uniqid('');
|
||||
|
@ -4630,6 +4631,11 @@ function ui_toggle(
|
|||
}
|
||||
|
||||
if ($disableToggle === false) {
|
||||
$position_div = 'relative';
|
||||
if ($position_tgl_div !== false) {
|
||||
$position_div = $position_tgl_div;
|
||||
}
|
||||
|
||||
// JQuery Toggle.
|
||||
$output .= '<script type="text/javascript">'."\n";
|
||||
$output .= ' var hide_tgl_ctrl_'.$uniqid.' = '.(int) $hidden_default.";\n";
|
||||
|
@ -4654,7 +4660,7 @@ function ui_toggle(
|
|||
$output .= ' if (hide_tgl_ctrl_'.$uniqid.") {\n";
|
||||
$output .= ' hide_tgl_ctrl_'.$uniqid." = 0;\n";
|
||||
$output .= " $('#tgl_div_".$uniqid."').css('height', 'auto');\n";
|
||||
$output .= " $('#tgl_div_".$uniqid."').css('position', 'relative');\n";
|
||||
$output .= " $('#tgl_div_".$uniqid."').css('position', '".$position_div."');\n";
|
||||
$output .= " $('#image_".$uniqid."').attr('style', 'rotate: ".$rotateA."');\n";
|
||||
$output .= " $('#checkbox-".$switch_name."').prop('checked', true);\n";
|
||||
$output .= $class_table;
|
||||
|
|
|
@ -995,6 +995,9 @@ function pandoraFlotSlicebar(
|
|||
}
|
||||
}
|
||||
|
||||
// Set array for realtime graphs
|
||||
var realtimeGraphs = [];
|
||||
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
function pandoraFlotArea(
|
||||
graph_id,
|
||||
|
@ -1007,6 +1010,21 @@ function pandoraFlotArea(
|
|||
params,
|
||||
events_array
|
||||
) {
|
||||
// Realtime graphs.
|
||||
if (typeof params.realtime !== "undefined") {
|
||||
realtimeGraphs.push({
|
||||
graph_id,
|
||||
values,
|
||||
legend,
|
||||
series_type,
|
||||
color,
|
||||
date_array,
|
||||
data_module_graph,
|
||||
params,
|
||||
events_array
|
||||
});
|
||||
}
|
||||
|
||||
//diferents vars
|
||||
var unit = params.unit ? params.unit : "";
|
||||
var homeurl = params.homeurl;
|
||||
|
@ -2462,15 +2480,23 @@ function pandoraFlotArea(
|
|||
if (Object.keys(update_legend).length == 0) {
|
||||
label_aux = legend[series.label];
|
||||
|
||||
$("#legend_" + graph_id + " .legendLabel")
|
||||
.eq(i)
|
||||
.html(
|
||||
label_aux +
|
||||
" value = " +
|
||||
number_format(y, 0, "", short_data, divisor) +
|
||||
" " +
|
||||
unit
|
||||
);
|
||||
if (params.graph_analytics === true) {
|
||||
var numberParams = {};
|
||||
numberParams.twoLines = true;
|
||||
$("#legend_" + graph_id + " .legendLabel .square-value")
|
||||
.eq(i)
|
||||
.html(number_format(y, 0, "", 1, divisor, numberParams));
|
||||
} else {
|
||||
$("#legend_" + graph_id + " .legendLabel")
|
||||
.eq(i)
|
||||
.html(
|
||||
label_aux +
|
||||
" value = " +
|
||||
number_format(y, 0, "", short_data, divisor) +
|
||||
" " +
|
||||
unit
|
||||
);
|
||||
}
|
||||
} else {
|
||||
$.each(update_legend, function(index, value) {
|
||||
if (typeof value[x - 1] !== "undefined") {
|
||||
|
@ -2844,12 +2870,16 @@ function pandoraFlotArea(
|
|||
// Add bottom margin in the legend
|
||||
// Estimated height of 24 (works fine with this data in all browsers)
|
||||
$("#legend_" + graph_id).css("margin-bottom", "10px");
|
||||
parent_height = parseInt(
|
||||
$("#menu_" + graph_id)
|
||||
.parent()
|
||||
.css("height")
|
||||
.split("px")[0]
|
||||
);
|
||||
|
||||
if (typeof params.realtime === "undefined" || params.realtime === false) {
|
||||
parent_height = parseInt(
|
||||
$("#menu_" + graph_id)
|
||||
.parent()
|
||||
.css("height")
|
||||
.split("px")[0]
|
||||
);
|
||||
}
|
||||
|
||||
adjust_menu(graph_id, plot, parent_height, width, show_legend);
|
||||
}
|
||||
}
|
||||
|
@ -2987,7 +3017,14 @@ function check_adaptions(graph_id) {
|
|||
});
|
||||
}
|
||||
|
||||
function number_format(number, force_integer, unit, short_data, divisor) {
|
||||
function number_format(
|
||||
number,
|
||||
force_integer,
|
||||
unit,
|
||||
short_data,
|
||||
divisor,
|
||||
params
|
||||
) {
|
||||
divisor = typeof divisor !== "undefined" ? divisor : 1000;
|
||||
var decimals = 2;
|
||||
|
||||
|
@ -3029,6 +3066,11 @@ function number_format(number, force_integer, unit, short_data, divisor) {
|
|||
number = 0;
|
||||
}
|
||||
|
||||
if (typeof params !== "undefined") {
|
||||
if (typeof params.twoLines !== "undefined" && params.twoLines === true);
|
||||
return number + "<br>" + shorts[pos] + unit;
|
||||
}
|
||||
|
||||
return number + " " + shorts[pos] + unit;
|
||||
}
|
||||
|
||||
|
|
|
@ -262,8 +262,14 @@ function flot_area_graph(
|
|||
(empty($params['line_width']) === true) ? $config['custom_graph_width'] : $params['line_width'],
|
||||
true
|
||||
);
|
||||
|
||||
$timestamp_top_fixed = '';
|
||||
if (isset($params['timestamp_top_fixed']) === true && empty($params['timestamp_top_fixed']) === false) {
|
||||
$timestamp_top_fixed = $params['timestamp_top_fixed'];
|
||||
}
|
||||
|
||||
$return .= "<div id='timestamp_$graph_id'
|
||||
class='timestamp_graph'
|
||||
class='timestamp_graph ".$timestamp_top_fixed." '
|
||||
style='font-size:".$params['font_size']."pt;
|
||||
display:none; position:absolute;
|
||||
background:#fff; border: solid 1px #aaa;
|
||||
|
@ -275,8 +281,20 @@ function flot_area_graph(
|
|||
$return .= 'noresizevc ';
|
||||
}
|
||||
|
||||
if (strpos($params['width'], '%') === false) {
|
||||
$width = 'width: '.$params['width'].'px;';
|
||||
} else {
|
||||
$width = 'width: '.$params['width'].';';
|
||||
}
|
||||
|
||||
if (strpos($params['graph_width'], '%') === false) {
|
||||
$width = 'width: '.$params['graph_width'].'px;';
|
||||
} else {
|
||||
$width = 'width: '.$params['graph_width'].';';
|
||||
}
|
||||
|
||||
$return .= 'graph'.$params['adapt_key']."'
|
||||
style=' width: ".$params['width'].'px;
|
||||
style='".$width.';
|
||||
height: '.$params['height']."px;'></div>";
|
||||
|
||||
$legend_top = 10;
|
||||
|
|
|
@ -0,0 +1,713 @@
|
|||
// Droppable options.
|
||||
var droppableOptions = {
|
||||
accept: ".draggable",
|
||||
hoverClass: "drops-hover",
|
||||
activeClass: "droppable-zone",
|
||||
drop: function(event, ui) {
|
||||
// Add new module.
|
||||
$(this)
|
||||
.data("modules")
|
||||
.push(ui.draggable.data("id-module"));
|
||||
|
||||
// Create elements.
|
||||
createDroppableZones(droppableOptions, getModulesByGraphs());
|
||||
}
|
||||
};
|
||||
|
||||
// Doc ready.
|
||||
$(document).ready(function() {
|
||||
// Hide toggles.
|
||||
$("#agents-toggle").hide();
|
||||
$("#groups-toggle").hide();
|
||||
$("#modules-toggle").hide();
|
||||
$("[data-button=pause-realtime]")
|
||||
.parent()
|
||||
.hide();
|
||||
|
||||
// Set droppable zones.
|
||||
$(".droppable").droppable(droppableOptions);
|
||||
});
|
||||
|
||||
// Interval change.
|
||||
$("#interval").change(function(e) {
|
||||
createDroppableZones(droppableOptions, getModulesByGraphs());
|
||||
});
|
||||
|
||||
// Collapse filters.
|
||||
$("div.filters-div-main > .filters-div-header > img").click(function(e) {
|
||||
if ($(".filters-div-main").hasClass("filters-div-main-collapsed") === true) {
|
||||
$(".filters-div-header > img").attr("src", "images/menu/contraer.svg");
|
||||
$(".filters-div-main").removeClass("filters-div-main-collapsed");
|
||||
$("#droppable-graphs").removeClass("droppable-graphs-collapsed");
|
||||
} else {
|
||||
$(".filters-div-header > img").attr("src", "images/menu/expandir.svg");
|
||||
$(".filters-div-main").addClass("filters-div-main-collapsed");
|
||||
$("#droppable-graphs").addClass("droppable-graphs-collapsed");
|
||||
}
|
||||
});
|
||||
|
||||
// Search left.
|
||||
$("#search-left").keyup(function(e) {
|
||||
if ($(this).val() !== "") {
|
||||
$.ajax({
|
||||
method: "POST",
|
||||
url: "ajax.php",
|
||||
dataType: "json",
|
||||
data: {
|
||||
page: "operation/reporting/graph_analytics",
|
||||
search_left: e.target.value
|
||||
},
|
||||
success: function(data) {
|
||||
if (data.agents || data.groups || data.modules) {
|
||||
var agentsToggle = $(
|
||||
"#agents-toggle > div[id^=tgl_div_] > div.white-box-content"
|
||||
);
|
||||
var groupsToggle = $(
|
||||
"#groups-toggle > div[id^=tgl_div_] > div.white-box-content"
|
||||
);
|
||||
var modulesToggle = $(
|
||||
"#modules-toggle > div[id^=tgl_div_] > div.white-box-content"
|
||||
);
|
||||
agentsToggle.empty();
|
||||
groupsToggle.empty();
|
||||
modulesToggle.empty();
|
||||
|
||||
if (data.agents) {
|
||||
$("#agents-toggle").show();
|
||||
data.agents.forEach(agent => {
|
||||
agentsToggle.append(
|
||||
`<div onclick="clickAgent(event.target);" data-id-agent="${agent.id_agente}" title="${agent.alias}">${agent.alias}</div>`
|
||||
);
|
||||
});
|
||||
} else {
|
||||
$("#agents-toggle").hide();
|
||||
}
|
||||
|
||||
if (data.groups) {
|
||||
$("#groups-toggle").show();
|
||||
data.groups.forEach(group => {
|
||||
groupsToggle.append(
|
||||
`<div onclick="clickGroup(event.target);" data-id-group="${group.id_grupo}" title="${group.nombre}">${group.nombre}</div>`
|
||||
);
|
||||
});
|
||||
} else {
|
||||
$("#groups-toggle").hide();
|
||||
}
|
||||
|
||||
if (data.modules) {
|
||||
$("#modules-toggle").show();
|
||||
data.modules.forEach(module => {
|
||||
modulesToggle.append(
|
||||
`<div class="draggable draggable-container" data-id-module="${module.id_agente_modulo}" title="${module.nombre}">
|
||||
<img class="draggable-icon" src="images/draggable.svg">
|
||||
<div class="draggable-module">
|
||||
<span class="draggable-module-name">${module.nombre}</span>
|
||||
<span class="draggable-agent-name">${module.alias}</span>
|
||||
</div>
|
||||
</div>`
|
||||
);
|
||||
});
|
||||
} else {
|
||||
$("#modules-toggle").hide();
|
||||
}
|
||||
|
||||
// Create draggable elements.
|
||||
$(".draggable").draggable({
|
||||
revert: "invalid",
|
||||
stack: ".draggable",
|
||||
helper: "clone"
|
||||
});
|
||||
} else {
|
||||
$("#agents-toggle").hide();
|
||||
$("#groups-toggle").hide();
|
||||
$("#modules-toggle").hide();
|
||||
}
|
||||
}
|
||||
});
|
||||
} else {
|
||||
$("#agents-toggle").hide();
|
||||
$("#groups-toggle").hide();
|
||||
$("#modules-toggle").hide();
|
||||
}
|
||||
});
|
||||
|
||||
function clickAgent(e) {
|
||||
$("#search-agent").val($(e).data("id-agent"));
|
||||
$("#search-group").val("");
|
||||
searchRight($("#search-right").val());
|
||||
}
|
||||
|
||||
function clickGroup(e) {
|
||||
$("#search-group").val($(e).data("id-group"));
|
||||
$("#search-agent").val("");
|
||||
searchRight($("#search-right").val());
|
||||
}
|
||||
|
||||
// Search right.
|
||||
$("#search-right").keyup(function(e) {
|
||||
if ($("#search-right") !== "") {
|
||||
searchRight(e.target.value);
|
||||
}
|
||||
});
|
||||
|
||||
function searchRight(freeSearch) {
|
||||
$.ajax({
|
||||
method: "POST",
|
||||
url: "ajax.php",
|
||||
dataType: "json",
|
||||
data: {
|
||||
page: "operation/reporting/graph_analytics",
|
||||
search_right: true,
|
||||
free_search: freeSearch,
|
||||
search_agent: $("#search-agent").val(),
|
||||
search_group: $("#search-group").val()
|
||||
},
|
||||
success: function(data) {
|
||||
var modulesRight = $("#modules-right");
|
||||
|
||||
if (data.modules) {
|
||||
modulesRight.empty();
|
||||
|
||||
data.modules.forEach(module => {
|
||||
modulesRight.append(
|
||||
`<div class="draggable draggable-container" data-id-module="${module.id_agente_modulo}" title="${module.nombre}">
|
||||
<img class="draggable-icon" src="images/draggable.svg">
|
||||
<div class="draggable-module">
|
||||
<span class="draggable-module-name">${module.nombre}</span>
|
||||
<span class="draggable-agent-name">${module.alias}</span>
|
||||
</div>
|
||||
</div>`
|
||||
);
|
||||
});
|
||||
|
||||
// Create draggable elements.
|
||||
$(".draggable").draggable({
|
||||
revert: "invalid",
|
||||
stack: ".draggable",
|
||||
helper: "clone"
|
||||
});
|
||||
} else {
|
||||
modulesRight.empty();
|
||||
console.error("NO DATA FOUND");
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function createDroppableZones(
|
||||
droppableOptions,
|
||||
modulesByGraphs,
|
||||
homeurl = "",
|
||||
getInterval = 0
|
||||
) {
|
||||
var url = "ajax.php";
|
||||
var interval = $("#interval").val();
|
||||
|
||||
if (homeurl !== "") {
|
||||
url = homeurl + "/ajax.php";
|
||||
}
|
||||
|
||||
if (getInterval !== 0) {
|
||||
interval = getInterval;
|
||||
}
|
||||
|
||||
// Clear graph area.
|
||||
$("#droppable-graphs").empty();
|
||||
|
||||
// Reset realtime data.
|
||||
realtimeGraphs = [];
|
||||
|
||||
// Graph modules.
|
||||
modulesByGraphs
|
||||
.slice()
|
||||
.reverse()
|
||||
.forEach(graph => {
|
||||
// Max modules by graph.
|
||||
var droppableClass = "";
|
||||
if (graph.length < 2) {
|
||||
droppableClass = "droppable";
|
||||
}
|
||||
|
||||
// Create graph div.
|
||||
var graphDiv = $(
|
||||
`<div class="${droppableClass}" data-modules="[${graph}]"></div>`
|
||||
);
|
||||
$("#droppable-graphs").prepend(graphDiv);
|
||||
|
||||
// Print graphs.
|
||||
$.ajax({
|
||||
method: "POST",
|
||||
url,
|
||||
dataType: "html",
|
||||
data: {
|
||||
page: "operation/reporting/graph_analytics",
|
||||
get_graphs: graph,
|
||||
interval
|
||||
},
|
||||
success: function(data) {
|
||||
if (data) {
|
||||
graphDiv.append(
|
||||
$(
|
||||
`<div class="draggable ui-draggable ui-draggable-handle">${data}</div>`
|
||||
)
|
||||
);
|
||||
|
||||
// Create remove button.
|
||||
if (
|
||||
graphDiv
|
||||
.children()
|
||||
.children()
|
||||
.hasClass("parent_graph") === true
|
||||
) {
|
||||
graphDiv
|
||||
.children()
|
||||
.children()
|
||||
.children(":first-child")
|
||||
.prepend(
|
||||
$(
|
||||
'<img src="images/delete.svg" class="remove-graph-analytics" onclick="removeGraph(this);">'
|
||||
)
|
||||
);
|
||||
} else {
|
||||
graphDiv
|
||||
.children()
|
||||
.append(
|
||||
$(
|
||||
'<img src="images/delete.svg" class="remove-graph-analytics" onclick="removeGraph(this);">'
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Create next droppable zone.
|
||||
graphDiv.after(
|
||||
$(
|
||||
`<div class="droppable droppable-default-zone droppable-new" data-modules="[]"><span class="drop-here">${dropHere}<span></div>`
|
||||
)
|
||||
);
|
||||
});
|
||||
|
||||
// Create first droppable zones and graphs.
|
||||
$("#droppable-graphs").prepend(
|
||||
$(
|
||||
`<div class="droppable droppable-default-zone droppable-new" data-modules="[]"><span class="drop-here">${dropHere}<span></div>`
|
||||
)
|
||||
);
|
||||
|
||||
// Set droppable zones.
|
||||
$(".droppable").droppable(droppableOptions);
|
||||
}
|
||||
|
||||
function getModulesByGraphs() {
|
||||
var modulesByGraphs = [];
|
||||
$("#droppable-graphs > div").each(function(i, v) {
|
||||
var modulesTmp = $(v).data("modules");
|
||||
if (modulesTmp.length > 0) {
|
||||
modulesByGraphs.push(modulesTmp);
|
||||
}
|
||||
});
|
||||
|
||||
return modulesByGraphs;
|
||||
}
|
||||
|
||||
function realtimeGraph() {
|
||||
realtimeGraphsTmp = realtimeGraphs;
|
||||
realtimeGraphs = [];
|
||||
|
||||
realtimeGraphsTmp.forEach(graph => {
|
||||
$.each(graph.series_type, function(i, v) {
|
||||
// Get new values.
|
||||
$.ajax({
|
||||
method: "POST",
|
||||
url: "ajax.php",
|
||||
dataType: "json",
|
||||
data: {
|
||||
page: "operation/reporting/graph_analytics",
|
||||
get_new_values: graph.values[i].agent_module_id,
|
||||
date_array: graph.date_array,
|
||||
data_module_graph: graph.data_module_graph,
|
||||
params: graph.params,
|
||||
suffix: i.slice(-1)
|
||||
},
|
||||
success: function(data) {
|
||||
if (data) {
|
||||
// Set new values
|
||||
graph.values[i].data = data[i].data;
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// New periods.
|
||||
var period = $("#interval").val();
|
||||
var time = Math.floor(Date.now() / 1000);
|
||||
|
||||
graph.params.date = time;
|
||||
|
||||
var date_array = {
|
||||
period,
|
||||
final_date: time,
|
||||
start_date: time - period
|
||||
};
|
||||
|
||||
pandoraFlotArea(
|
||||
graph.graph_id,
|
||||
graph.values,
|
||||
graph.legend,
|
||||
graph.series_type,
|
||||
graph.color,
|
||||
date_array,
|
||||
graph.data_module_graph,
|
||||
graph.params,
|
||||
graph.events_array
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
// Action buttons.
|
||||
// Start/Pause Realtime.
|
||||
var realtimeGraphInterval;
|
||||
$("[data-button=pause-realtime]")
|
||||
.parent()
|
||||
.hide();
|
||||
|
||||
$("[data-button=start-realtime]").click(function(e) {
|
||||
$("[data-button=start-realtime]")
|
||||
.parent()
|
||||
.hide();
|
||||
$("[data-button=pause-realtime]")
|
||||
.parent()
|
||||
.show();
|
||||
|
||||
realtimeGraphInterval = setInterval(realtimeGraph, 5000);
|
||||
});
|
||||
|
||||
$("[data-button=pause-realtime]").click(function(e) {
|
||||
$("[data-button=pause-realtime]")
|
||||
.parent()
|
||||
.hide();
|
||||
$("[data-button=start-realtime]")
|
||||
.parent()
|
||||
.show();
|
||||
|
||||
clearInterval(realtimeGraphInterval);
|
||||
});
|
||||
|
||||
// New graph.
|
||||
$("[data-button=new]").click(function(e) {
|
||||
confirmDialog({
|
||||
title: titleNew,
|
||||
message: messageNew,
|
||||
onAccept: function() {
|
||||
$("#droppable-graphs").empty();
|
||||
|
||||
// Create graph div.
|
||||
$("#droppable-graphs").prepend(
|
||||
$(
|
||||
`<div class="droppable droppable-default-zone ui-droppable" data-modules="[]"><span class="drop-here">${dropHere}<span></div>`
|
||||
)
|
||||
);
|
||||
$(".droppable").droppable(droppableOptions);
|
||||
|
||||
// Reset realtime button.
|
||||
$("[data-button=pause-realtime]")
|
||||
.parent()
|
||||
.hide();
|
||||
$("[data-button=start-realtime]")
|
||||
.parent()
|
||||
.show();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// Save graps modal.
|
||||
$("[data-button=save]").click(function(e) {
|
||||
// Filter save mode selector
|
||||
$("#save_filter_row1").show();
|
||||
$("#save_filter_row2").show();
|
||||
$("#update_filter_row1").hide();
|
||||
$("#radiobtn0002").prop("checked", false);
|
||||
$("#radiobtn0001").prop("checked", true);
|
||||
$("#text-id_name").val("");
|
||||
|
||||
$("[name='filter_mode']").click(function() {
|
||||
if ($(this).val() == "new") {
|
||||
$("#save_filter_row1").show();
|
||||
$("#save_filter_row2").show();
|
||||
$("#submit-save_filter").show();
|
||||
$("#update_filter_row1").hide();
|
||||
} else {
|
||||
$("#save_filter_row1").hide();
|
||||
$("#save_filter_row2").hide();
|
||||
$("#update_filter_row1").show();
|
||||
$("#submit-save_filter").hide();
|
||||
}
|
||||
});
|
||||
|
||||
$("#save-filter-select").dialog({
|
||||
resizable: true,
|
||||
draggable: true,
|
||||
modal: false,
|
||||
closeOnEscape: true,
|
||||
width: 350
|
||||
});
|
||||
});
|
||||
|
||||
// Save filter button.
|
||||
function save_new_filter() {
|
||||
$.ajax({
|
||||
method: "POST",
|
||||
url: "ajax.php",
|
||||
dataType: "html",
|
||||
data: {
|
||||
page: "operation/reporting/graph_analytics",
|
||||
save_filter: $("#text-id_name").val(),
|
||||
graphs: getModulesByGraphs(),
|
||||
interval: $("#interval").val()
|
||||
},
|
||||
success: function(data) {
|
||||
if (data == "saved") {
|
||||
confirmDialog({
|
||||
title: titleSave,
|
||||
message: messageSave,
|
||||
hideCancelButton: true,
|
||||
onAccept: function() {
|
||||
$(
|
||||
"button.ui-button.ui-corner-all.ui-widget.ui-button-icon-only.ui-dialog-titlebar-close"
|
||||
).click();
|
||||
}
|
||||
});
|
||||
} else {
|
||||
var message = messageSaveEmpty;
|
||||
if (data === "") {
|
||||
message = messageSaveEmptyName;
|
||||
}
|
||||
confirmDialog({
|
||||
title: titleError,
|
||||
message,
|
||||
hideCancelButton: true
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Update filter button.
|
||||
function save_update_filter() {
|
||||
confirmDialog({
|
||||
title: titleUpdate,
|
||||
message: messageUpdate,
|
||||
onAccept: function() {
|
||||
$.ajax({
|
||||
method: "POST",
|
||||
url: "ajax.php",
|
||||
dataType: "html",
|
||||
data: {
|
||||
page: "operation/reporting/graph_analytics",
|
||||
update_filter: $("#overwrite_filter").val(),
|
||||
graphs: getModulesByGraphs(),
|
||||
interval: $("#interval").val()
|
||||
},
|
||||
success: function(data) {
|
||||
if (data == "updated") {
|
||||
confirmDialog({
|
||||
title: titleUpdateConfirm,
|
||||
message: messageUpdateConfirm,
|
||||
hideCancelButton: true,
|
||||
onAccept: function() {
|
||||
$(
|
||||
"button.ui-button.ui-corner-all.ui-widget.ui-button-icon-only.ui-dialog-titlebar-close"
|
||||
).click();
|
||||
}
|
||||
});
|
||||
} else {
|
||||
confirmDialog({
|
||||
title: titleUpdateError,
|
||||
message: messageUpdateError,
|
||||
hideCancelButton: true
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Load graps modal.
|
||||
$("[data-button=load]").click(function(e) {
|
||||
$("#load-filter-select").dialog({
|
||||
resizable: true,
|
||||
draggable: true,
|
||||
modal: false,
|
||||
closeOnEscape: true,
|
||||
width: "auto"
|
||||
});
|
||||
});
|
||||
|
||||
// Load filter button.
|
||||
function load_filter_values(id = 0, homeurl) {
|
||||
var url = "ajax.php";
|
||||
var filterId = $("#filter_id").val();
|
||||
|
||||
if (id !== 0) {
|
||||
filterId = id;
|
||||
url = homeurl + "/ajax.php";
|
||||
}
|
||||
|
||||
if (id === 0) {
|
||||
confirmDialog({
|
||||
title: titleLoad,
|
||||
message: messageLoad,
|
||||
onAccept: function() {
|
||||
loadFilter(url, filterId, homeurl, id);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
loadFilter(url, filterId, homeurl, id);
|
||||
}
|
||||
}
|
||||
|
||||
function loadFilter(url, filterId, homeurl, id) {
|
||||
$.ajax({
|
||||
method: "POST",
|
||||
url,
|
||||
dataType: "json",
|
||||
data: {
|
||||
page: "operation/reporting/graph_analytics",
|
||||
load_filter: filterId
|
||||
},
|
||||
success: function(data) {
|
||||
if (data) {
|
||||
createDroppableZones(
|
||||
droppableOptions,
|
||||
data.graphs,
|
||||
homeurl,
|
||||
data.interval
|
||||
);
|
||||
if (id === 0) {
|
||||
$("#interval")
|
||||
.val(data.interval)
|
||||
.trigger("change");
|
||||
}
|
||||
|
||||
$(
|
||||
"button.ui-button.ui-corner-all.ui-widget.ui-button-icon-only.ui-dialog-titlebar-close"
|
||||
).click();
|
||||
|
||||
// Reset realtime button.
|
||||
if (id === 0) {
|
||||
$("[data-button=pause-realtime]")
|
||||
.parent()
|
||||
.hide();
|
||||
$("[data-button=start-realtime]")
|
||||
.parent()
|
||||
.show();
|
||||
}
|
||||
} else {
|
||||
confirmDialog({
|
||||
title: titleLoadConfirm,
|
||||
message: messageLoadConfirm,
|
||||
hideCancelButton: true
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Share button.
|
||||
$("[data-button=share]").click(function(e) {
|
||||
$("#share-select").dialog({
|
||||
resizable: true,
|
||||
draggable: true,
|
||||
modal: false,
|
||||
closeOnEscape: true,
|
||||
width: "auto"
|
||||
});
|
||||
});
|
||||
|
||||
$("#button-share-modal").click(function(e) {
|
||||
const hash = $("#hash_share").val();
|
||||
const idFilter = btoa($("#share-id").val());
|
||||
const idUser = $("#id_user").val();
|
||||
|
||||
const queryParams = "hash=" + hash + "&id=" + idFilter + "&id_user=" + idUser;
|
||||
|
||||
window.open(
|
||||
configHomeurl +
|
||||
"/operation/reporting/graph_analytics_public.php?" +
|
||||
queryParams
|
||||
);
|
||||
});
|
||||
|
||||
// Export button.
|
||||
$("[data-button=export]").click(function(e) {
|
||||
$("#export-select").dialog({
|
||||
resizable: true,
|
||||
draggable: true,
|
||||
modal: false,
|
||||
closeOnEscape: true,
|
||||
width: "auto",
|
||||
title: titleExport
|
||||
});
|
||||
});
|
||||
|
||||
$("#button-export-modal").click(function(e) {
|
||||
const filter = parseInt($("#export-filter-id").val());
|
||||
const group = parseInt($("#export-group-id").val());
|
||||
|
||||
if (filter !== 0) {
|
||||
$.ajax({
|
||||
method: "POST",
|
||||
url: "ajax.php",
|
||||
dataType: "html",
|
||||
data: {
|
||||
page: "operation/reporting/graph_analytics",
|
||||
export_filter: filter,
|
||||
group
|
||||
},
|
||||
success: function(data) {
|
||||
if (data) {
|
||||
confirmDialog({
|
||||
title: titleExportConfirm,
|
||||
message: data + " " + messageExportConfirm,
|
||||
hideCancelButton: true,
|
||||
onAccept: function() {
|
||||
$(
|
||||
"button.ui-button.ui-corner-all.ui-widget.ui-button-icon-only.ui-dialog-titlebar-close"
|
||||
).click();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// Remove graph.
|
||||
function removeGraph(e) {
|
||||
confirmDialog({
|
||||
title: titleRemoveConfirm,
|
||||
message: messageRemoveConfirm,
|
||||
onAccept: function() {
|
||||
if (
|
||||
$(e)
|
||||
.parent()
|
||||
.hasClass("menu_graph") === true
|
||||
) {
|
||||
$(e)
|
||||
.parent()
|
||||
.parent()
|
||||
.parent()
|
||||
.parent()
|
||||
.remove();
|
||||
} else {
|
||||
$(e)
|
||||
.parent()
|
||||
.parent()
|
||||
.remove();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
|
@ -0,0 +1,371 @@
|
|||
div#main {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
div.box-flat.white_table_graph > div[id^="tgl_div_"] {
|
||||
border-bottom-left-radius: 8px;
|
||||
border-bottom-right-radius: 8px;
|
||||
width: 228px;
|
||||
}
|
||||
|
||||
div.box-flat.white_table_graph > div[id^="tgl_div_"] > div.white-box-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex-wrap: nowrap;
|
||||
align-items: flex-start;
|
||||
justify-content: flex-start;
|
||||
}
|
||||
|
||||
div.box-flat.white_table_graph
|
||||
> div[id^="tgl_div_"]
|
||||
> div.white-box-content
|
||||
> [data-id-agent],
|
||||
div.box-flat.white_table_graph
|
||||
> div[id^="tgl_div_"]
|
||||
> div.white-box-content
|
||||
> [data-id-group] {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
div#menu_tab ul li,
|
||||
div#menu_tab ul li span {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: nowrap;
|
||||
align-items: center;
|
||||
font-size: 14px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
div#menu_tab ul.mn li.nomn.tab_operation img {
|
||||
margin-right: 3px;
|
||||
}
|
||||
|
||||
div#menu_tab ul li:hover,
|
||||
div#menu_tab ul li span:hover {
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
div.main-div {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: nowrap;
|
||||
min-height: calc(100vh - 160px);
|
||||
}
|
||||
|
||||
div.main-div.graph-analytics-public {
|
||||
min-height: calc(100vh - 2px);
|
||||
}
|
||||
|
||||
div.padding-div {
|
||||
margin: 0;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
div.margin-div {
|
||||
margin: 10px;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
div.filters-div-main {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
width: 500px;
|
||||
min-width: 500px;
|
||||
border-right: 1px solid var(--border-dark-color);
|
||||
}
|
||||
|
||||
div.filters-div-main.filters-div-main-collapsed {
|
||||
width: 35px;
|
||||
min-width: 20px;
|
||||
border-right: 0px;
|
||||
}
|
||||
|
||||
div.filters-div-main.filters-div-main-collapsed
|
||||
*:not(.filters-div-header):not(.filters-div-header > img) {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.droppable-graphs-collapsed {
|
||||
margin-left: -30px;
|
||||
}
|
||||
|
||||
div.filters-div-main > .filters-div-header {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: nowrap;
|
||||
justify-content: space-between;
|
||||
margin: 10px;
|
||||
}
|
||||
|
||||
div.filters-div-main > .filters-div-header > img {
|
||||
width: 20px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
div.filters-div-submain {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: nowrap;
|
||||
justify-content: flex-start;
|
||||
align-items: flex-start;
|
||||
height: calc(100% - 51px);
|
||||
}
|
||||
|
||||
div.filter-div {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex-wrap: nowrap;
|
||||
width: 230px;
|
||||
min-width: 230px;
|
||||
max-width: 230px;
|
||||
height: 100%;
|
||||
padding: 10px;
|
||||
border-top: 1px solid var(--border-dark-color);
|
||||
}
|
||||
|
||||
.filters-left-div {
|
||||
border-right: 1px solid var(--border-dark-color);
|
||||
}
|
||||
|
||||
div.filters-right-div {
|
||||
width: 230px;
|
||||
min-width: 230px;
|
||||
max-width: 230px;
|
||||
}
|
||||
|
||||
.search-graph-analytics {
|
||||
background-image: url(../../images/details.svg);
|
||||
background-position: center right 10px;
|
||||
background-repeat: no-repeat;
|
||||
background-size: 17px;
|
||||
width: 100%;
|
||||
margin: 10px 0;
|
||||
padding-right: 30px;
|
||||
}
|
||||
|
||||
div.graphs-div-main {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.handle-graph {
|
||||
cursor: grab;
|
||||
}
|
||||
|
||||
#droppable-graphs {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex-wrap: nowrap;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.interval-div {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: nowrap;
|
||||
justify-content: center;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
/* Draggable */
|
||||
.draggable.ui-draggable-dragging {
|
||||
width: 20%;
|
||||
}
|
||||
|
||||
.draggable {
|
||||
width: 100%;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.draggable-container {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
margin-left: -10px;
|
||||
padding-top: 3px;
|
||||
padding-bottom: 3px;
|
||||
border-bottom: 1px solid #f0f0f0;
|
||||
}
|
||||
|
||||
.draggable-container:last-child {
|
||||
border-bottom: 0px;
|
||||
}
|
||||
|
||||
.draggable-module {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex-wrap: nowrap;
|
||||
}
|
||||
|
||||
.draggable-icon {
|
||||
height: 25px;
|
||||
}
|
||||
|
||||
.draggable-module > span {
|
||||
line-height: 10pt;
|
||||
}
|
||||
|
||||
.draggable-module > span.draggable-module-name {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.draggable-module > span.draggable-agent-name {
|
||||
color: #8a96a6;
|
||||
}
|
||||
|
||||
/* Droppable */
|
||||
#droppable-graphs * {
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.droppable {
|
||||
width: 100%;
|
||||
/* height: 20px; */
|
||||
margin-bottom: 5px;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
#droppable-graphs .droppable-zone {
|
||||
background-color: #0077ff80;
|
||||
border: 2px dashed #0077ff;
|
||||
border-radius: 6px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
#droppable-graphs .droppable-zone > div {
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
#droppable-graphs .drops-hover {
|
||||
background-color: #82b92e80;
|
||||
border: 2px dashed #82b92e;
|
||||
}
|
||||
|
||||
#droppable-graphs .droppable.droppable-default-zone:not(.droppable-new) {
|
||||
height: 70px;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
#droppable-graphs .droppable.droppable-default-zone.droppable-new {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
#droppable-graphs
|
||||
.droppable.droppable-default-zone.droppable-new
|
||||
> span.drop-here {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#droppable-graphs .droppable.droppable-default-zone > span.drop-here {
|
||||
font-size: 15pt;
|
||||
font-weight: bold;
|
||||
color: #0077ff;
|
||||
}
|
||||
|
||||
#droppable-graphs
|
||||
.droppable.droppable-default-zone.droppable-new.ui-droppable-active
|
||||
> span.drop-here {
|
||||
display: initial;
|
||||
}
|
||||
|
||||
#droppable-graphs .droppable.droppable-default-zone.ui-droppable-active {
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
#droppable-graphs
|
||||
.droppable.droppable-default-zone.ui-droppable-active.drops-hover
|
||||
> span.drop-here {
|
||||
color: #82b92e;
|
||||
}
|
||||
|
||||
#droppable-graphs .droppable .draggable.ui-draggable.ui-draggable-handle {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#droppable-graphs .parent_graph {
|
||||
padding-top: 40px;
|
||||
}
|
||||
|
||||
#droppable-graphs .timestamp_graph {
|
||||
top: 15px;
|
||||
}
|
||||
|
||||
#droppable-graphs .menu_graph {
|
||||
left: 85%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
div.timestamp-top-fixed {
|
||||
top: 15px !important;
|
||||
}
|
||||
|
||||
div.graph-analytics-legend-main {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
div.graph-analytics-legend-square {
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
max-width: 30px;
|
||||
margin-right: 5px;
|
||||
padding-right: 3px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-end;
|
||||
flex-wrap: nowrap;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
div.graph-analytics-legend-square > span {
|
||||
text-align: right;
|
||||
color: #fff;
|
||||
line-height: 9pt;
|
||||
}
|
||||
|
||||
div.graph-analytics-legend-square > span.square-unit {
|
||||
width: 30px;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
div.graph-analytics-legend {
|
||||
display: flex;
|
||||
flex-direction: column-reverse;
|
||||
flex-wrap: nowrap;
|
||||
}
|
||||
|
||||
div.graph-analytics-legend > span {
|
||||
line-height: 12pt;
|
||||
}
|
||||
|
||||
div.graph-analytics-legend > span:first-child {
|
||||
font-weight: normal;
|
||||
font-size: 8pt;
|
||||
margin-left: 5px;
|
||||
}
|
||||
|
||||
#droppable-graphs td.legendColorBox {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#droppable-graphs .remove-graph-analytics {
|
||||
width: 20px;
|
||||
opacity: 0;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
#droppable-graphs > div:hover .remove-graph-analytics {
|
||||
opacity: 1;
|
||||
}
|
|
@ -32,6 +32,7 @@
|
|||
--secondary-color: #ffffff;
|
||||
--input-border: #c0ccdc;
|
||||
--border-color: #eee;
|
||||
--border-dark-color: #e1e1e1;
|
||||
--text-color: #333;
|
||||
}
|
||||
|
||||
|
|
|
@ -471,6 +471,12 @@ if ($access_console_node === true) {
|
|||
'godmode/reporting/graph_builder',
|
||||
];
|
||||
|
||||
|
||||
// Graph analytics.
|
||||
$sub['operation/reporting/graph_analytics']['text'] = __('Graph analytics');
|
||||
$sub['operation/reporting/graph_analytics']['id'] = 'Graph_analytics';
|
||||
|
||||
|
||||
if (check_acl($config['id_user'], 0, 'RR')
|
||||
|| check_acl($config['id_user'], 0, 'RW')
|
||||
|| check_acl($config['id_user'], 0, 'RM')
|
||||
|
|
|
@ -0,0 +1,942 @@
|
|||
<?php
|
||||
/**
|
||||
* Graph viewer.
|
||||
*
|
||||
* @category Reporting - Graph analytics
|
||||
* @package Pandora FMS
|
||||
* @subpackage Community
|
||||
* @version 1.0.0
|
||||
* @license See below
|
||||
*
|
||||
* ______ ___ _______ _______ ________
|
||||
* | __ \.-----.--.--.--| |.-----.----.-----. | ___| | | __|
|
||||
* | __/| _ | | _ || _ | _| _ | | ___| |__ |
|
||||
* |___| |___._|__|__|_____||_____|__| |___._| |___| |__|_|__|_______|
|
||||
*
|
||||
* ============================================================================
|
||||
* Copyright (c) 2005-2023 Pandora FMS
|
||||
* Please see https://pandorafms.com/community/ for full contribution list
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation for version 2.
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
* ============================================================================
|
||||
*/
|
||||
|
||||
// Begin.
|
||||
global $config;
|
||||
|
||||
check_login();
|
||||
|
||||
use PandoraFMS\User;
|
||||
|
||||
// Requires.
|
||||
ui_require_css_file('graph_analytics');
|
||||
require_once 'include/functions_custom_graphs.php';
|
||||
|
||||
// Ajax.
|
||||
if (is_ajax()) {
|
||||
$search_left = get_parameter('search_left');
|
||||
$search_right = get_parameter('search_right');
|
||||
$get_graphs = get_parameter('get_graphs');
|
||||
$save_filter = get_parameter('save_filter');
|
||||
$load_filter = get_parameter('load_filter');
|
||||
$update_filter = get_parameter('update_filter');
|
||||
$get_new_values = get_parameter('get_new_values');
|
||||
$export_filter = get_parameter('export_filter');
|
||||
|
||||
if (empty($search_left) === false) {
|
||||
$output = [];
|
||||
$search = io_safe_input($search_left);
|
||||
|
||||
// Agents.
|
||||
// Concatenate AW and AD permisions to get all the possible groups where the user can manage.
|
||||
$user_groupsAW = users_get_groups($config['id_user'], 'AW');
|
||||
$user_groupsAD = users_get_groups($config['id_user'], 'AD');
|
||||
|
||||
$user_groups = ($user_groupsAW + $user_groupsAD);
|
||||
$user_groups_to_sql = implode(',', array_keys($user_groups));
|
||||
|
||||
$search_sql = ' AND (nombre LIKE "%%'.$search.'%%" OR alias LIKE "%%'.$search.'%%")';
|
||||
|
||||
$sql = sprintf(
|
||||
'SELECT *
|
||||
FROM tagente
|
||||
LEFT JOIN tagent_secondary_group tasg
|
||||
ON tagente.id_agente = tasg.id_agent
|
||||
WHERE (tagente.id_grupo IN (%s) OR tasg.id_group IN (%s))
|
||||
%s
|
||||
GROUP BY tagente.id_agente
|
||||
ORDER BY tagente.nombre',
|
||||
$user_groups_to_sql,
|
||||
$user_groups_to_sql,
|
||||
$search_sql
|
||||
);
|
||||
|
||||
$output['agents'] = db_get_all_rows_sql($sql);
|
||||
|
||||
// Groups.
|
||||
$search_sql = ' AND (nombre LIKE "%%'.$search.'%%" OR description LIKE "%%'.$search.'%%")';
|
||||
|
||||
$sql = sprintf(
|
||||
'SELECT id_grupo, nombre, icon, description
|
||||
FROM tgrupo
|
||||
WHERE (id_grupo IN (%s))
|
||||
%s
|
||||
ORDER BY nombre',
|
||||
$user_groups_to_sql,
|
||||
$search_sql
|
||||
);
|
||||
|
||||
$output['groups'] = db_get_all_rows_sql($sql);
|
||||
|
||||
// Modules.
|
||||
$result_agents = [];
|
||||
$sql_result = db_get_all_rows_sql('SELECT id_agente FROM tagente WHERE id_grupo IN ('.$user_groups_to_sql.')');
|
||||
|
||||
foreach ($sql_result as $result) {
|
||||
array_push($result_agents, $result['id_agente']);
|
||||
}
|
||||
|
||||
$id_agents = implode(',', $result_agents);
|
||||
$search_sql = ' AND (tam.nombre LIKE "%%'.$search.'%%" OR tam.descripcion LIKE "%%'.$search.'%%")';
|
||||
|
||||
$sql = sprintf(
|
||||
'SELECT tam.id_agente_modulo, tam.nombre, tam.descripcion, ta.alias
|
||||
FROM tagente_modulo tam
|
||||
INNER JOIN tagente ta ON ta.id_agente = tam.id_agente
|
||||
WHERE (tam.id_agente IN (%s))
|
||||
%s
|
||||
ORDER BY tam.nombre',
|
||||
$id_agents,
|
||||
$search_sql
|
||||
);
|
||||
|
||||
$output['modules'] = db_get_all_rows_sql($sql);
|
||||
|
||||
// Return.
|
||||
echo json_encode($output);
|
||||
return;
|
||||
}
|
||||
|
||||
if (empty($search_right) === false) {
|
||||
$output = [];
|
||||
$search = io_safe_input(get_parameter('free_search'));
|
||||
$agent = get_parameter('search_agent');
|
||||
$group = get_parameter('search_group');
|
||||
|
||||
$search_sql = ' AND (tam.nombre LIKE "%%'.$search.'%%" OR tam.descripcion LIKE "%%'.$search.'%%")';
|
||||
|
||||
// Agent.
|
||||
if (empty($agent) === false) {
|
||||
$sql = sprintf(
|
||||
'SELECT tam.id_agente_modulo, tam.nombre, tam.descripcion, ta.alias
|
||||
FROM tagente_modulo tam
|
||||
INNER JOIN tagente ta ON ta.id_agente = tam.id_agente
|
||||
WHERE (tam.id_agente = %s)
|
||||
%s
|
||||
ORDER BY tam.nombre',
|
||||
$agent,
|
||||
$search_sql
|
||||
);
|
||||
|
||||
$output['modules'] = db_get_all_rows_sql($sql);
|
||||
}
|
||||
|
||||
// Group.
|
||||
if (empty($group) === false) {
|
||||
$sql = sprintf(
|
||||
'SELECT tam.id_agente_modulo, tam.nombre, tam.descripcion, ta.alias
|
||||
FROM tagente_modulo tam
|
||||
INNER JOIN tagente ta ON ta.id_agente = tam.id_agente
|
||||
WHERE (ta.id_grupo = %s)
|
||||
%s
|
||||
ORDER BY tam.nombre',
|
||||
$group,
|
||||
$search_sql
|
||||
);
|
||||
|
||||
$output['modules'] = db_get_all_rows_sql($sql);
|
||||
}
|
||||
|
||||
// Return.
|
||||
echo json_encode($output);
|
||||
return;
|
||||
}
|
||||
|
||||
// Graph.
|
||||
if (empty($get_graphs) === false) {
|
||||
$interval = (int) get_parameter('interval');
|
||||
$modules = $get_graphs;
|
||||
|
||||
$params = [
|
||||
'period' => $interval,
|
||||
'width' => '100%',
|
||||
'graph_width' => '85%',
|
||||
'height' => 100,
|
||||
'date' => time(),
|
||||
'percentil' => null,
|
||||
'fullscale' => 1,
|
||||
'type_graph' => 'line',
|
||||
'timestamp_top_fixed' => 'timestamp-top-fixed',
|
||||
'graph_analytics' => true,
|
||||
'realtime' => true,
|
||||
];
|
||||
|
||||
$params_combined = [
|
||||
'stacked' => 2,
|
||||
'labels' => [],
|
||||
'modules_series' => $modules,
|
||||
'id_graph' => null,
|
||||
'return' => 1,
|
||||
'graph_analytics' => true,
|
||||
];
|
||||
|
||||
$graph_return = graphic_combined_module(
|
||||
$modules,
|
||||
$params,
|
||||
$params_combined
|
||||
);
|
||||
|
||||
$graph_return .= "
|
||||
<script>
|
||||
$('div.parent_graph > .legend_background').each(function (index, element) {
|
||||
$(element).next().html('');
|
||||
$(element).next().append(element);
|
||||
});
|
||||
</script>
|
||||
";
|
||||
|
||||
echo $graph_return;
|
||||
return;
|
||||
}
|
||||
|
||||
// Save filter.
|
||||
if (empty($save_filter) === false) {
|
||||
$graphs = get_parameter('graphs');
|
||||
$interval = (int) get_parameter('interval');
|
||||
|
||||
if (empty($save_filter) === true) {
|
||||
echo __('Empty name');
|
||||
return;
|
||||
}
|
||||
|
||||
if (empty($graphs) === true) {
|
||||
echo __('It is not possible to create the filter if you have not made any change');
|
||||
return;
|
||||
}
|
||||
|
||||
$id_filter = db_process_sql_insert(
|
||||
'tgraph_analytics_filter',
|
||||
[
|
||||
'filter_name' => $save_filter,
|
||||
'user_id' => $config['id_user'],
|
||||
'graph_modules' => json_encode($graphs),
|
||||
'interval' => $interval,
|
||||
]
|
||||
);
|
||||
|
||||
if ($id_filter > 0) {
|
||||
echo 'saved';
|
||||
return;
|
||||
} else {
|
||||
echo __('It is not possible to create the filter if you have not made any change');
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Update filter.
|
||||
if (empty($update_filter) === false) {
|
||||
$graphs = get_parameter('graphs');
|
||||
$interval = (int) get_parameter('interval');
|
||||
|
||||
if (empty($graphs) === true) {
|
||||
echo __('It is not possible to update the filter if you have not made any change');
|
||||
return;
|
||||
}
|
||||
|
||||
$update_filter = db_process_sql_update(
|
||||
'tgraph_analytics_filter',
|
||||
[
|
||||
'graph_modules' => json_encode($graphs),
|
||||
'interval' => $interval,
|
||||
],
|
||||
['id' => $update_filter]
|
||||
);
|
||||
|
||||
if ($update_filter > 0) {
|
||||
echo 'updated';
|
||||
return;
|
||||
} else {
|
||||
echo __('No updated');
|
||||
return;
|
||||
}
|
||||
|
||||
echo $update_filter;
|
||||
return;
|
||||
}
|
||||
|
||||
// Load filter.
|
||||
if (empty($load_filter) === false) {
|
||||
$data = [];
|
||||
$data['graphs'] = json_decode(db_get_value('graph_modules', 'tgraph_analytics_filter', 'id', $load_filter));
|
||||
$data['interval'] = db_get_value('tgraph_analytics_filter.interval', 'tgraph_analytics_filter', 'id', $load_filter);
|
||||
|
||||
echo json_encode($data);
|
||||
return;
|
||||
}
|
||||
|
||||
// Get new values.
|
||||
if (empty($get_new_values) === false) {
|
||||
$data = [];
|
||||
|
||||
$agent_module_id = $get_new_values;
|
||||
$date_array = get_parameter('date_array');
|
||||
$data_module_graph = get_parameter('data_module_graph');
|
||||
$params = get_parameter('params');
|
||||
$suffix = get_parameter('suffix');
|
||||
|
||||
// Stract data.
|
||||
$array_data_module = grafico_modulo_sparse_data(
|
||||
$agent_module_id,
|
||||
$date_array,
|
||||
$data_module_graph,
|
||||
$params,
|
||||
$suffix
|
||||
);
|
||||
|
||||
echo json_encode($array_data_module);
|
||||
return;
|
||||
}
|
||||
|
||||
// Export graphs.
|
||||
if (empty($export_filter) === false) {
|
||||
$counter = 0;
|
||||
$filter = get_parameter('export_filter');
|
||||
$group = get_parameter('group');
|
||||
|
||||
$filter_name = db_get_value('filter_name', 'tgraph_analytics_filter', 'id', $filter);
|
||||
$graphs = json_decode(db_get_value('graph_modules', 'tgraph_analytics_filter', 'id', $filter));
|
||||
$interval = db_get_value('tgraph_analytics_filter.interval', 'tgraph_analytics_filter', 'id', $filter);
|
||||
|
||||
foreach ($graphs as $graph) {
|
||||
$id_graph = db_process_sql_insert(
|
||||
'tgraph',
|
||||
[
|
||||
'id_user' => $config['id_user'],
|
||||
'id_group' => $group,
|
||||
'name' => $filter_name.' ('.__('Graph').' '.($counter + 1).')',
|
||||
'description' => __('Created from Graph analytics. Filter:').' '.$filter_name.'. '.__('Graph').' '.($counter + 1),
|
||||
'period' => $interval,
|
||||
'stacked' => 2,
|
||||
]
|
||||
);
|
||||
|
||||
if ($id_graph > 0) {
|
||||
$counter++;
|
||||
$field_order = 1;
|
||||
|
||||
foreach ($graph as $module) {
|
||||
$id_graph_source = db_process_sql_insert(
|
||||
'tgraph_source',
|
||||
[
|
||||
'id_graph' => $id_graph,
|
||||
'id_server' => 0,
|
||||
'id_agent_module' => $module,
|
||||
'weight' => 1,
|
||||
'label' => '',
|
||||
'field_order' => $field_order,
|
||||
]
|
||||
);
|
||||
|
||||
$field_order++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
echo $counter;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Save filter modal.
|
||||
echo '<div id="save-filter-select" style="width:350px;" class="invisible">';
|
||||
if (check_acl($config['id_user'], 0, 'RW') === 1 || check_acl($config['id_user'], 0, 'RM') === 1) {
|
||||
echo '<div id="info_box"></div>';
|
||||
$table = new StdClass;
|
||||
$table->id = 'save_filter_form';
|
||||
$table->width = '100%';
|
||||
$table->cellspacing = 4;
|
||||
$table->cellpadding = 4;
|
||||
$table->class = 'databox no_border';
|
||||
|
||||
$table->styleTable = 'font-weight: bold; text-align:left;';
|
||||
|
||||
$data = [];
|
||||
$table->rowid[0] = 'update_save_selector';
|
||||
$data[0] = html_print_div(
|
||||
[
|
||||
'style' => 'display: flex;',
|
||||
'content' => html_print_radio_button(
|
||||
'filter_mode',
|
||||
'new',
|
||||
__('New filter'),
|
||||
true,
|
||||
true
|
||||
),
|
||||
],
|
||||
true
|
||||
);
|
||||
|
||||
$data[1] = html_print_div(
|
||||
[
|
||||
'style' => 'display: flex;',
|
||||
'content' => html_print_radio_button(
|
||||
'filter_mode',
|
||||
'update',
|
||||
__('Update filter'),
|
||||
false,
|
||||
true
|
||||
),
|
||||
],
|
||||
true
|
||||
);
|
||||
|
||||
$table->data[] = $data;
|
||||
$table->rowclass[] = '';
|
||||
|
||||
$data = [];
|
||||
$table->rowid[1] = 'save_filter_row1';
|
||||
$data[0] = __('Filter name');
|
||||
$data[0] .= html_print_input_text('id_name', '', '', 15, 255, true);
|
||||
|
||||
$data[1] = html_print_submit_button(
|
||||
__('Save filter'),
|
||||
'save_filter',
|
||||
false,
|
||||
[
|
||||
'class' => 'mini ',
|
||||
'icon' => 'save',
|
||||
'style' => 'margin-left: 175px; width: 125px;',
|
||||
'onclick' => 'save_new_filter();',
|
||||
],
|
||||
true
|
||||
);
|
||||
|
||||
$table->data[] = $data;
|
||||
$table->rowclass[] = '';
|
||||
|
||||
$data = [];
|
||||
$table->rowid[2] = 'save_filter_row2';
|
||||
|
||||
$table->data[] = $data;
|
||||
$table->rowclass[] = '';
|
||||
|
||||
$data = [];
|
||||
$table->rowid[3] = 'update_filter_row1';
|
||||
$data[0] = __('Overwrite filter');
|
||||
|
||||
$select_filters_update = graph_analytics_filter_select();
|
||||
|
||||
$data[0] .= html_print_select(
|
||||
$select_filters_update,
|
||||
'overwrite_filter',
|
||||
'',
|
||||
'',
|
||||
'',
|
||||
0,
|
||||
true
|
||||
);
|
||||
$table->rowclass[] = 'display-grid';
|
||||
$data[1] = html_print_submit_button(
|
||||
__('Update filter'),
|
||||
'update_filter',
|
||||
false,
|
||||
[
|
||||
'class' => 'mini ',
|
||||
'icon' => 'save',
|
||||
'style' => 'margin-left: 155px; width: 145px;',
|
||||
'onclick' => 'save_update_filter();',
|
||||
],
|
||||
true
|
||||
);
|
||||
|
||||
$table->data[] = $data;
|
||||
$table->rowclass[] = '';
|
||||
|
||||
html_print_table($table);
|
||||
} else {
|
||||
include 'general/noaccess.php';
|
||||
}
|
||||
|
||||
echo '</div>';
|
||||
|
||||
// Load filter modal.
|
||||
$filters = graph_analytics_filter_select();
|
||||
|
||||
echo '<div id="load-filter-select" class="load-filter-modal invisible">';
|
||||
|
||||
$table = new StdClass;
|
||||
$table->id = 'load_filter_form';
|
||||
$table->width = '100%';
|
||||
$table->cellspacing = 4;
|
||||
$table->cellpadding = 4;
|
||||
$table->class = 'databox no_border';
|
||||
|
||||
$table->styleTable = 'font-weight: bold; color: #555; text-align:left;';
|
||||
$filter_id_width = 'w100p';
|
||||
|
||||
$data = [];
|
||||
$table->rowid[3] = 'update_filter_row1';
|
||||
$data[0] = __('Load filter');
|
||||
$data[0] .= html_print_select(
|
||||
$filters,
|
||||
'filter_id',
|
||||
'',
|
||||
'',
|
||||
__('None'),
|
||||
0,
|
||||
true,
|
||||
false,
|
||||
true,
|
||||
'',
|
||||
false,
|
||||
'width:'.$filter_id_width.';'
|
||||
);
|
||||
|
||||
$table->rowclass[] = 'display-grid';
|
||||
$data[1] = html_print_submit_button(
|
||||
__('Load filter'),
|
||||
'load_filter',
|
||||
false,
|
||||
[
|
||||
'class' => 'mini w30p',
|
||||
'icon' => 'load',
|
||||
'style' => 'margin-left: 208px; width: 130px;',
|
||||
'onclick' => 'load_filter_values();',
|
||||
],
|
||||
true
|
||||
);
|
||||
$data[1] .= html_print_input_hidden('load_filter', 1, true);
|
||||
$table->data[] = $data;
|
||||
$table->rowclass[] = '';
|
||||
|
||||
html_print_table($table);
|
||||
echo '</div>';
|
||||
|
||||
// Share modal.
|
||||
echo '<div id="share-select" class="load-filter-modal invisible">';
|
||||
|
||||
$table = new StdClass;
|
||||
$table->id = 'share_form';
|
||||
$table->width = '100%';
|
||||
$table->cellspacing = 4;
|
||||
$table->cellpadding = 4;
|
||||
$table->class = 'databox no_border';
|
||||
|
||||
$table->styleTable = 'font-weight: bold; color: #555; text-align:left;';
|
||||
$filter_id_width = 'w100p';
|
||||
|
||||
$data = [];
|
||||
$table->rowid[3] = 'share_row1';
|
||||
$data[0] = __('Share');
|
||||
$data[0] .= html_print_select(
|
||||
$filters,
|
||||
'share-id',
|
||||
'',
|
||||
'',
|
||||
'',
|
||||
0,
|
||||
true,
|
||||
false,
|
||||
true,
|
||||
'',
|
||||
false,
|
||||
'width:'.$filter_id_width.';'
|
||||
);
|
||||
|
||||
$table->rowclass[] = 'display-grid';
|
||||
$data[1] = html_print_submit_button(
|
||||
__('Share'),
|
||||
'share-modal',
|
||||
false,
|
||||
[
|
||||
'class' => 'mini w30p',
|
||||
'icon' => 'next',
|
||||
'style' => 'margin-left: 208px; width: 130px;',
|
||||
'onclick' => '',
|
||||
],
|
||||
true
|
||||
);
|
||||
$data[1] .= html_print_input_hidden('share-hidden', 1, true);
|
||||
$table->data[] = $data;
|
||||
$table->rowclass[] = '';
|
||||
|
||||
html_print_table($table);
|
||||
echo '</div>';
|
||||
|
||||
// Export graphs.
|
||||
echo '<div id="export-select" class="load-filter-modal invisible">';
|
||||
|
||||
$table = new StdClass;
|
||||
$table->id = 'share_form';
|
||||
$table->width = '100%';
|
||||
$table->cellspacing = 4;
|
||||
$table->cellpadding = 4;
|
||||
$table->class = 'databox no_border';
|
||||
|
||||
$table->styleTable = 'font-weight: bold; color: #555; text-align:left;';
|
||||
$filter_id_width = 'w100p';
|
||||
|
||||
$data = [];
|
||||
$table->rowid[3] = 'export_row1';
|
||||
$data[0] = __('Export filter');
|
||||
$data[0] .= html_print_select(
|
||||
$filters,
|
||||
'export-filter-id',
|
||||
'',
|
||||
'',
|
||||
'',
|
||||
0,
|
||||
true,
|
||||
false,
|
||||
true,
|
||||
'',
|
||||
false,
|
||||
'width:'.$filter_id_width.';'
|
||||
);
|
||||
|
||||
$user_groups = users_get_groups($config['user'], 'RW');
|
||||
$data[1] = __('Group');
|
||||
$data[1] .= html_print_select(
|
||||
$user_groups,
|
||||
'export-group-id',
|
||||
'',
|
||||
'',
|
||||
'',
|
||||
0,
|
||||
true,
|
||||
false,
|
||||
true,
|
||||
'',
|
||||
false,
|
||||
'width:'.$filter_id_width.';'
|
||||
);
|
||||
|
||||
$table->rowclass[] = 'display-grid';
|
||||
$data[2] = html_print_submit_button(
|
||||
__('Export'),
|
||||
'export-modal',
|
||||
false,
|
||||
[
|
||||
'class' => 'mini w30p',
|
||||
'icon' => 'next',
|
||||
'style' => 'margin-left: 208px; width: 130px;',
|
||||
'onclick' => '',
|
||||
],
|
||||
true
|
||||
);
|
||||
$data[1] .= html_print_input_hidden('export-hidden', 1, true);
|
||||
$table->data[] = $data;
|
||||
$table->rowclass[] = '';
|
||||
|
||||
html_print_table($table);
|
||||
echo '</div>';
|
||||
|
||||
|
||||
// Header & Actions.
|
||||
$title_tab = __('Start realtime');
|
||||
$tab_start_realtime = [
|
||||
'text' => '<span data-button="start-realtime">'.html_print_image(
|
||||
'images/change-active.svg',
|
||||
true,
|
||||
[
|
||||
'title' => $title_tab,
|
||||
'class' => 'invert_filter main_menu_icon',
|
||||
]
|
||||
).$title_tab.'</span>',
|
||||
];
|
||||
|
||||
$title_tab = __('Pause realtime');
|
||||
$tab_pause_realtime = [
|
||||
'text' => '<span data-button="pause-realtime">'.html_print_image(
|
||||
'images/change-pause.svg',
|
||||
true,
|
||||
[
|
||||
'title' => $title_tab,
|
||||
'class' => 'invert_filter main_menu_icon',
|
||||
]
|
||||
).$title_tab.'</span>',
|
||||
];
|
||||
|
||||
$title_tab = __('New');
|
||||
$tab_new = [
|
||||
'text' => '<span data-button="new">'.html_print_image(
|
||||
'images/plus-black.svg',
|
||||
true,
|
||||
[
|
||||
'title' => $title_tab,
|
||||
'class' => 'invert_filter main_menu_icon',
|
||||
]
|
||||
).$title_tab.'</span>',
|
||||
];
|
||||
|
||||
$title_tab = __('Save');
|
||||
$tab_save = [
|
||||
'text' => '<span data-button="save">'.html_print_image(
|
||||
'images/save_mc.png',
|
||||
true,
|
||||
[
|
||||
'title' => $title_tab,
|
||||
'class' => 'invert_filter main_menu_icon',
|
||||
]
|
||||
).$title_tab.'</span>',
|
||||
];
|
||||
|
||||
$title_tab = __('Load');
|
||||
$tab_load = [
|
||||
'text' => '<span data-button="load">'.html_print_image(
|
||||
'images/logs@svg.svg',
|
||||
true,
|
||||
[
|
||||
'title' => $title_tab,
|
||||
'class' => 'invert_filter main_menu_icon',
|
||||
]
|
||||
).$title_tab.'</span>',
|
||||
];
|
||||
|
||||
// Hash for auto-auth in public link.
|
||||
$hash = User::generatePublicHash();
|
||||
|
||||
$title_tab = __('Share');
|
||||
$tab_share = [
|
||||
'text' => '<span data-button="share">'.html_print_image(
|
||||
'images/responses.svg',
|
||||
true,
|
||||
[
|
||||
'title' => $title_tab,
|
||||
'class' => 'invert_filter main_menu_icon',
|
||||
]
|
||||
).$title_tab.'</span><input id="hash_share" type="hidden" value="'.$hash.'">
|
||||
<input id="id_user" type="hidden" value="'.$config['id_user'].'">',
|
||||
];
|
||||
|
||||
$title_tab = __('Export to custom graph');
|
||||
$tab_export = [
|
||||
'text' => '<span data-button="export">'.html_print_image(
|
||||
'images/module-graph.svg',
|
||||
true,
|
||||
[
|
||||
'title' => $title_tab,
|
||||
'class' => 'invert_filter main_menu_icon',
|
||||
]
|
||||
).$title_tab.'</span>',
|
||||
];
|
||||
|
||||
ui_print_standard_header(
|
||||
__('Graph analytics'),
|
||||
'images/menu/reporting.svg',
|
||||
false,
|
||||
'',
|
||||
false,
|
||||
[
|
||||
$tab_export,
|
||||
$tab_share,
|
||||
$tab_load,
|
||||
$tab_save,
|
||||
$tab_new,
|
||||
$tab_pause_realtime,
|
||||
$tab_start_realtime,
|
||||
],
|
||||
[
|
||||
[
|
||||
'link' => '',
|
||||
'label' => __('Reporting'),
|
||||
],
|
||||
]
|
||||
);
|
||||
|
||||
// Content.
|
||||
$left_content = '';
|
||||
$right_content = '';
|
||||
|
||||
$left_content .= '
|
||||
<div class="filters-div-header">
|
||||
<div></div>
|
||||
<img src="images/menu/contraer.svg">
|
||||
</div>
|
||||
<div class="filters-div-submain">
|
||||
<div class="filter-div filters-left-div">
|
||||
<input id="search-left" name="search-left" placeholder="Enter keywords to search" type="search" class="search-graph-analytics">
|
||||
<br>
|
||||
'.ui_toggle(
|
||||
'',
|
||||
__('Agents'),
|
||||
'agents-toggle',
|
||||
'agents-toggle',
|
||||
true,
|
||||
true,
|
||||
'',
|
||||
'white-box-content',
|
||||
'box-flat white_table_graph',
|
||||
'images/arrow@svg.svg',
|
||||
'images/arrow@svg.svg',
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
'',
|
||||
'',
|
||||
null,
|
||||
null,
|
||||
false,
|
||||
false,
|
||||
'static'
|
||||
).ui_toggle(
|
||||
'',
|
||||
__('Groups'),
|
||||
'groups-toggle',
|
||||
'groups-toggle',
|
||||
true,
|
||||
true,
|
||||
'',
|
||||
'white-box-content',
|
||||
'box-flat white_table_graph',
|
||||
'images/arrow@svg.svg',
|
||||
'images/arrow@svg.svg',
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
'',
|
||||
'',
|
||||
null,
|
||||
null,
|
||||
false,
|
||||
false,
|
||||
'static'
|
||||
).ui_toggle(
|
||||
'',
|
||||
__('Modules'),
|
||||
'modules-toggle',
|
||||
'modules-toggle',
|
||||
true,
|
||||
true,
|
||||
'',
|
||||
'white-box-content',
|
||||
'box-flat white_table_graph',
|
||||
'images/arrow@svg.svg',
|
||||
'images/arrow@svg.svg',
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
'',
|
||||
'',
|
||||
null,
|
||||
null,
|
||||
false,
|
||||
false,
|
||||
'static'
|
||||
).'
|
||||
</div>
|
||||
<div class="filter-div filters-right-div ">
|
||||
<input id="search-right" placeholder="Enter keywords to search" type="search" class="search-graph-analytics">
|
||||
<input id="search-agent" type="hidden" value="">
|
||||
<input id="search-group" type="hidden" value="">
|
||||
<div id="modules-right"></div>
|
||||
</div>
|
||||
</div>
|
||||
';
|
||||
|
||||
$intervals = [];
|
||||
$intervals[SECONDS_1HOUR] = _('Last ').human_time_description_raw(SECONDS_1HOUR, true, 'large');
|
||||
$intervals[SECONDS_6HOURS] = _('Last ').human_time_description_raw(SECONDS_6HOURS, true, 'large');
|
||||
$intervals[SECONDS_12HOURS] = _('Last ').human_time_description_raw(SECONDS_12HOURS, true, 'large');
|
||||
$intervals[SECONDS_1DAY] = _('Last ').human_time_description_raw(SECONDS_1DAY, true, 'large');
|
||||
$intervals[SECONDS_2DAY] = _('Last ').human_time_description_raw(SECONDS_2DAY, true, 'large');
|
||||
$intervals[SECONDS_1WEEK] = _('Last ').human_time_description_raw(SECONDS_1WEEK, true, 'large');
|
||||
|
||||
$right_content .= '<div class="interval-div">'.html_print_select(
|
||||
$intervals,
|
||||
'interval',
|
||||
SECONDS_12HOURS,
|
||||
'',
|
||||
'',
|
||||
0,
|
||||
true,
|
||||
false,
|
||||
false,
|
||||
''
|
||||
).'</div>';
|
||||
|
||||
$right_content .= '
|
||||
<div id="droppable-graphs">
|
||||
<div class="droppable droppable-default-zone" data-modules="[]"><span class="drop-here">'.__('Drop here').'<span></div>
|
||||
</div>
|
||||
';
|
||||
|
||||
$filters_div = html_print_div(
|
||||
[
|
||||
'class' => 'filters-div-main',
|
||||
'content' => $left_content,
|
||||
],
|
||||
true
|
||||
);
|
||||
|
||||
$graphs_div = html_print_div(
|
||||
[
|
||||
'class' => 'padding-div graphs-div-main',
|
||||
'content' => $right_content,
|
||||
],
|
||||
true
|
||||
);
|
||||
|
||||
html_print_div(
|
||||
[
|
||||
'class' => 'white_box main-div',
|
||||
'content' => $filters_div.$graphs_div,
|
||||
]
|
||||
);
|
||||
|
||||
ui_require_javascript_file('graph_analytics', 'include/javascript/', true);
|
||||
?>
|
||||
|
||||
<script>
|
||||
const dropHere = "<?php echo __('Drop here'); ?>";
|
||||
|
||||
const titleNew = "<?php echo __('New graph'); ?>";
|
||||
const messageNew = "<?php echo __('If you create a new graph, the current settings will be deleted. Please save the graph if you want to keep it.'); ?>";
|
||||
|
||||
const titleSave = "<?php echo __('Saved successfully'); ?>";
|
||||
const messageSave = "<?php echo __('The filter has been saved successfully'); ?>";
|
||||
|
||||
const messageSaveEmpty = "<?php echo __('It is not possible to create the filter if you have not made any change'); ?>";
|
||||
const messageSaveEmptyName = "<?php echo __('Empty name'); ?>";
|
||||
|
||||
const titleError = "<?php echo __('Error'); ?>";
|
||||
|
||||
const titleUpdate = "<?php echo __('Override filter?'); ?>";
|
||||
const messageUpdate = "<?php echo __('Do you want to overwrite the filter?'); ?>";
|
||||
|
||||
const titleUpdateConfirm = "<?php echo __('Updated successfully'); ?>";
|
||||
const messageUpdateConfirm = "<?php echo __('The filter has been updated successfully'); ?>";
|
||||
|
||||
const titleUpdateError = "<?php echo __('Error'); ?>";
|
||||
const messageUpdateError = "<?php echo __('It is not possible to update the filter if you have not made any change'); ?>";
|
||||
|
||||
const titleLoad = "<?php echo __('Overwrite current graph?'); ?>";
|
||||
const messageLoad = "<?php echo __('If you load a filter, it will clear the current graph'); ?>";
|
||||
|
||||
const titleLoadConfirm = "<?php echo __('Error'); ?>";
|
||||
const messageLoadConfirm = "<?php echo __('Error loading filter'); ?>";
|
||||
|
||||
const titleExport = "<?php echo __('Export to custom graph'); ?>";
|
||||
|
||||
const titleExportConfirm = "<?php echo __('Exported successfully'); ?>";
|
||||
const messageExportConfirm = "<?php echo __('graphs have been created in Custom graphs'); ?>";
|
||||
|
||||
const titleRemoveConfirm = "<?php echo __('Delete graph'); ?>";
|
||||
const messageRemoveConfirm = "<?php echo __('Do you want to delete the graph? Remember to save the changes.'); ?>";
|
||||
</script>
|
|
@ -0,0 +1,191 @@
|
|||
<?php
|
||||
/**
|
||||
* Graph viewer.
|
||||
*
|
||||
* @category Reporting - Graph analytics
|
||||
* @package Pandora FMS
|
||||
* @subpackage Community
|
||||
* @version 1.0.0
|
||||
* @license See below
|
||||
*
|
||||
* ______ ___ _______ _______ ________
|
||||
* | __ \.-----.--.--.--| |.-----.----.-----. | ___| | | __|
|
||||
* | __/| _ | | _ || _ | _| _ | | ___| |__ |
|
||||
* |___| |___._|__|__|_____||_____|__| |___._| |___| |__|_|__|_______|
|
||||
*
|
||||
* ============================================================================
|
||||
* Copyright (c) 2005-2023 Pandora FMS
|
||||
* Please see https://pandorafms.com/community/ for full contribution list
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation for version 2.
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
* ============================================================================
|
||||
*/
|
||||
|
||||
// Requires.
|
||||
require_once '../../include/config.php';
|
||||
require_once $config['homedir'].'/vendor/autoload.php';
|
||||
require_once '../../include/functions_custom_graphs.php';
|
||||
|
||||
use PandoraFMS\User;
|
||||
|
||||
$hash = (string) get_parameter('hash');
|
||||
|
||||
// Check input hash.
|
||||
// DO NOT move it after of get parameter user id.
|
||||
if (User::validatePublicHash($hash) !== true) {
|
||||
db_pandora_audit(
|
||||
AUDIT_LOG_GRAPH_ANALYTICS_PUBLIC,
|
||||
'Trying to access public graph analytics'
|
||||
);
|
||||
include 'general/noaccess.php';
|
||||
exit;
|
||||
}
|
||||
|
||||
$text_subtitle = isset($config['rb_product_name_alt']) ? '' : ' - '.__('the Flexible Monitoring System');
|
||||
echo '
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<link rel="icon" href="../../images/pandora.ico" type="image/ico">
|
||||
<title>'.get_product_name().$text_subtitle.'</title>
|
||||
';
|
||||
|
||||
// CSS.
|
||||
ui_require_css_file('common', 'include/styles/', true);
|
||||
ui_require_css_file('pandora', 'include/styles/', true);
|
||||
ui_require_css_file('discovery', 'include/styles/', true);
|
||||
ui_require_css_file('register', 'include/styles/', true);
|
||||
ui_require_css_file('order_interpreter', 'include/styles/', true);
|
||||
ui_require_css_file('graph_analytics', 'include/styles/', true);
|
||||
ui_require_css_file('jquery-ui.min', 'include/styles/js/', true);
|
||||
ui_require_css_file('jquery-ui_custom', 'include/styles/js/', true);
|
||||
ui_require_css_file('introjs', 'include/styles/js/', true);
|
||||
ui_require_css_file('events', 'include/styles/', true);
|
||||
|
||||
// JS.
|
||||
ui_require_javascript_file('jquery.current', 'include/javascript/', true);
|
||||
ui_require_javascript_file('jquery.pandora', 'include/javascript/', true);
|
||||
ui_require_javascript_file('jquery-ui.min', 'include/javascript/', true);
|
||||
ui_require_javascript_file('jquery.countdown', 'include/javascript/', true);
|
||||
ui_require_javascript_file('pandora', 'include/javascript/', true);
|
||||
ui_require_javascript_file('pandora_ui', 'include/javascript/', true);
|
||||
ui_require_javascript_file('pandora_events', 'include/javascript/', true);
|
||||
ui_require_javascript_file('select2.min', 'include/javascript/', true);
|
||||
// ui_require_javascript_file('connection_check', 'include/javascript/', true);
|
||||
ui_require_javascript_file('encode_decode_base64', 'include/javascript/', true);
|
||||
ui_require_javascript_file('qrcode', 'include/javascript/', true);
|
||||
ui_require_javascript_file('intro', 'include/javascript/', true);
|
||||
ui_require_javascript_file('clippy', 'include/javascript/', true);
|
||||
ui_require_javascript_file('underscore-min', 'include/javascript/', true);
|
||||
|
||||
echo '
|
||||
<script type="text/javascript">
|
||||
var phpTimezone = "'.date_default_timezone_get().'";
|
||||
var configHomeurl = "'.$config['homeurl'].'";
|
||||
</script>
|
||||
';
|
||||
|
||||
|
||||
|
||||
ui_require_javascript_file('date', 'include/javascript/timezone/src/', true);
|
||||
ui_require_javascript_file('jquery.flot.min', 'include/graphs/flot/', true);
|
||||
ui_require_javascript_file('jquery.flot.time', 'include/graphs/flot/', true);
|
||||
ui_require_javascript_file('jquery.flot.pie', 'include/graphs/flot/', true);
|
||||
ui_require_javascript_file('jquery.flot.crosshair.min', 'include/graphs/flot/', true);
|
||||
ui_require_javascript_file('jquery.flot.stack.min', 'include/graphs/flot/', true);
|
||||
ui_require_javascript_file('jquery.flot.selection.min', 'include/graphs/flot/', true);
|
||||
ui_require_javascript_file('jquery.flot.resize.min', 'include/graphs/flot/', true);
|
||||
ui_require_javascript_file('jquery.flot.threshold', 'include/graphs/flot/', true);
|
||||
ui_require_javascript_file('jquery.flot.threshold.multiple', 'include/graphs/flot/', true);
|
||||
ui_require_javascript_file('jquery.flot.symbol.min', 'include/graphs/flot/', true);
|
||||
ui_require_javascript_file('jquery.flot.exportdata.pandora', 'include/graphs/flot/', true);
|
||||
ui_require_javascript_file('jquery.flot.axislabels', 'include/graphs/flot/', true);
|
||||
ui_require_javascript_file('pandora.flot', 'include/graphs/flot/', true);
|
||||
ui_require_javascript_file('chart', 'include/graphs/chartjs/', true);
|
||||
ui_require_javascript_file('chartjs-plugin-datalabels.min', 'include/graphs/chartjs/', true);
|
||||
|
||||
|
||||
|
||||
ui_require_javascript_file('graph_analytics', 'include/javascript/', true);
|
||||
|
||||
|
||||
echo '
|
||||
</head>
|
||||
<body>
|
||||
';
|
||||
|
||||
// Content.
|
||||
$right_content = '';
|
||||
|
||||
$right_content .= '
|
||||
<div id="droppable-graphs">
|
||||
<div class="droppable droppable-default-zone" data-modules="[]"><span class="drop-here">'.__('Drop here').'<span></div>
|
||||
</div>
|
||||
';
|
||||
|
||||
$graphs_div = html_print_div(
|
||||
[
|
||||
'class' => 'padding-div graphs-div-main',
|
||||
'content' => $right_content,
|
||||
],
|
||||
true
|
||||
);
|
||||
|
||||
html_print_div(
|
||||
[
|
||||
'class' => 'white_box main-div graph-analytics-public',
|
||||
'content' => $graphs_div,
|
||||
]
|
||||
);
|
||||
|
||||
?>
|
||||
|
||||
<script>
|
||||
const dropHere = "<?php echo __('Drop here'); ?>";
|
||||
|
||||
const titleNew = "<?php echo __('New graph'); ?>";
|
||||
const messageNew = "<?php echo __('If you create a new graph, the current settings will be deleted. Please save the graph if you want to keep it.'); ?>";
|
||||
|
||||
const titleSave = "<?php echo __('Saved successfully'); ?>";
|
||||
const messageSave = "<?php echo __('The filter has been saved successfully'); ?>";
|
||||
|
||||
const messageSaveEmpty = "<?php echo __('Empty graph'); ?>";
|
||||
const messageSaveEmptyName = "<?php echo __('Empty name'); ?>";
|
||||
|
||||
const titleError = "<?php echo __('Error'); ?>";
|
||||
|
||||
const titleUpdate = "<?php echo __('Override filter?'); ?>";
|
||||
const messageUpdate = "<?php echo __('Do you want to overwrite the filter?'); ?>";
|
||||
|
||||
const titleUpdateConfirm = "<?php echo __('Updated successfully'); ?>";
|
||||
const messageUpdateConfirm = "<?php echo __('The filter has been updated successfully'); ?>";
|
||||
|
||||
const titleUpdateError = "<?php echo __('Error'); ?>";
|
||||
const messageUpdateError = "<?php echo __('Empty graph'); ?>";
|
||||
|
||||
const titleLoad = "<?php echo __('Overwrite current graph?'); ?>";
|
||||
const messageLoad = "<?php echo __('If you load a filter, it will clear the current graph'); ?>";
|
||||
|
||||
const titleLoadConfirm = "<?php echo __('Error'); ?>";
|
||||
const messageLoadConfirm = "<?php echo __('Error loading filter'); ?>";
|
||||
|
||||
|
||||
document.addEventListener("DOMContentLoaded", (event) => {
|
||||
const hash = "<?php echo get_parameter('hash'); ?>";
|
||||
const idFilter = atob("<?php echo get_parameter('id'); ?>");
|
||||
const idUser = "<?php echo get_parameter('id_user'); ?>";
|
||||
|
||||
load_filter_values(idFilter, configHomeurl);
|
||||
});
|
||||
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
|
@ -4421,4 +4421,16 @@ CREATE TABLE IF NOT EXISTS `tsca` (
|
|||
`remediation` text DEFAULT NULL,
|
||||
`compliance` text DEFAULT NULL,
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=UTF8MB4;
|
||||
|
||||
-- ---------------------------------------------------------------------
|
||||
-- Table `tgraph_analytics_filter`
|
||||
-- ---------------------------------------------------------------------
|
||||
CREATE TABLE IF NOT EXISTS `tgraph_analytics_filter` (
|
||||
`id` INT NOT NULL auto_increment,
|
||||
`filter_name` VARCHAR(45) NULL,
|
||||
`user_id` VARCHAR(255) NULL,
|
||||
`graph_modules` TEXT NULL,
|
||||
`interval` INT NULL,
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=UTF8MB4;
|
Loading…
Reference in New Issue