Merge remote-tracking branch 'origin/develop' into ent-2707-System-Uptime-data-show-bug

This commit is contained in:
Luis Calvo 2019-06-17 16:59:33 +02:00
commit 6b2bb1a138
90 changed files with 811 additions and 256 deletions

View File

@ -1,5 +1,5 @@
package: pandorafms-agent-unix package: pandorafms-agent-unix
Version: 7.0NG.735-190610 Version: 7.0NG.735-190617
Architecture: all Architecture: all
Priority: optional Priority: optional
Section: admin Section: admin

View File

@ -14,7 +14,7 @@
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
pandora_version="7.0NG.735-190610" pandora_version="7.0NG.735-190617"
echo "Test if you has the tools for to make the packages." echo "Test if you has the tools for to make the packages."
whereis dpkg-deb | cut -d":" -f2 | grep dpkg-deb > /dev/null whereis dpkg-deb | cut -d":" -f2 | grep dpkg-deb > /dev/null

View File

@ -42,7 +42,7 @@ my $Sem = undef;
my $ThreadSem = undef; my $ThreadSem = undef;
use constant AGENT_VERSION => '7.0NG.735'; use constant AGENT_VERSION => '7.0NG.735';
use constant AGENT_BUILD => '190610'; use constant AGENT_BUILD => '190617';
# Agent log default file size maximum and instances # Agent log default file size maximum and instances
use constant DEFAULT_MAX_LOG_SIZE => 600000; use constant DEFAULT_MAX_LOG_SIZE => 600000;

View File

@ -3,7 +3,7 @@
# #
%define name pandorafms_agent_unix %define name pandorafms_agent_unix
%define version 7.0NG.735 %define version 7.0NG.735
%define release 190610 %define release 190617
Summary: Pandora FMS Linux agent, PERL version Summary: Pandora FMS Linux agent, PERL version
Name: %{name} Name: %{name}

View File

@ -3,7 +3,7 @@
# #
%define name pandorafms_agent_unix %define name pandorafms_agent_unix
%define version 7.0NG.735 %define version 7.0NG.735
%define release 190610 %define release 190617
Summary: Pandora FMS Linux agent, PERL version Summary: Pandora FMS Linux agent, PERL version
Name: %{name} Name: %{name}

View File

@ -10,7 +10,7 @@
# ********************************************************************** # **********************************************************************
PI_VERSION="7.0NG.735" PI_VERSION="7.0NG.735"
PI_BUILD="190610" PI_BUILD="190617"
OS_NAME=`uname -s` OS_NAME=`uname -s`
FORCE=0 FORCE=0

View File

@ -30,7 +30,7 @@ my $Output = 'module';
my $Verbose = 0; my $Verbose = 0;
# Index file storage directory, with a trailing '/' # Index file storage directory, with a trailing '/'
my $Idx_dir=($^O =~ /win/i)?'.\\':'/tmp/'; my $Idx_dir=($^O =~ /win/i)?"$ENV{'TMP'}\\":"/tmp/";
# Log file # Log file
my $Log_file = ''; my $Log_file = '';

View File

@ -186,7 +186,7 @@ UpgradeApplicationID
{} {}
Version Version
{190610} {190617}
ViewReadme ViewReadme
{Yes} {Yes}

View File

@ -30,7 +30,7 @@ using namespace Pandora;
using namespace Pandora_Strutils; using namespace Pandora_Strutils;
#define PATH_SIZE _MAX_PATH+1 #define PATH_SIZE _MAX_PATH+1
#define PANDORA_VERSION ("7.0NG.735(Build 190610)") #define PANDORA_VERSION ("7.0NG.735(Build 190617)")
string pandora_path; string pandora_path;
string pandora_dir; string pandora_dir;

View File

@ -11,7 +11,7 @@ BEGIN
VALUE "LegalCopyright", "Artica ST" VALUE "LegalCopyright", "Artica ST"
VALUE "OriginalFilename", "PandoraAgent.exe" VALUE "OriginalFilename", "PandoraAgent.exe"
VALUE "ProductName", "Pandora FMS Windows Agent" VALUE "ProductName", "Pandora FMS Windows Agent"
VALUE "ProductVersion", "(7.0NG.735(Build 190610))" VALUE "ProductVersion", "(7.0NG.735(Build 190617))"
VALUE "FileVersion", "1.0.0.0" VALUE "FileVersion", "1.0.0.0"
END END
END END

View File

@ -1,5 +1,5 @@
package: pandorafms-console package: pandorafms-console
Version: 7.0NG.735-190610 Version: 7.0NG.735-190617
Architecture: all Architecture: all
Priority: optional Priority: optional
Section: admin Section: admin

View File

@ -14,7 +14,7 @@
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
pandora_version="7.0NG.735-190610" pandora_version="7.0NG.735-190617"
package_pear=0 package_pear=0
package_pandora=1 package_pandora=1

View File

@ -139,8 +139,9 @@ function get_logs_size($file)
function get_status_logs($path) function get_status_logs($path)
{ {
$status_server_log = ''; $status_server_log = '';
$size_server_log = get_logs_size($path); $size_server_log = number_format(get_logs_size($path));
if ($size_server_log <= 1048576) { $size_server_log = (0 + str_replace(',', '', $size_server_log));
if ($size_server_log <= 10485760) {
$status_server_log = "<a style ='color: green;text-decoration: none;'>Normal Status</a><a style ='text-decoration: none;'>&nbsp&nbsp You have less than 10 MB of logs</a>"; $status_server_log = "<a style ='color: green;text-decoration: none;'>Normal Status</a><a style ='text-decoration: none;'>&nbsp&nbsp You have less than 10 MB of logs</a>";
} else { } else {
$status_server_log = "<a class= 'content' style= 'color: red;text-decoration: none;'>Warning Status</a><a style ='text-decoration: none;'>&nbsp&nbsp You have more than 10 MB of logs</a>"; $status_server_log = "<a class= 'content' style= 'color: red;text-decoration: none;'>Warning Status</a><a style ='text-decoration: none;'>&nbsp&nbsp You have more than 10 MB of logs</a>";

View File

@ -322,7 +322,7 @@ if ($create_modules) {
} else if (preg_match('/ifAdminStatus/', $name_array[1])) { } else if (preg_match('/ifAdminStatus/', $name_array[1])) {
$module_type = 2; $module_type = 2;
} else if (preg_match('/ifOperStatus/', $name_array[1])) { } else if (preg_match('/ifOperStatus/', $name_array[1])) {
$module_type = 18; $module_type = 2;
} else { } else {
$module_type = 4; $module_type = 4;
} }
@ -684,4 +684,3 @@ function snmp_changed_by_multiple_snmp (event, id_snmp, selected) {
/* ]]> */ /* ]]> */
</script> </script>

View File

@ -83,8 +83,8 @@ $data[3] = html_print_input_password(
true, true,
$disabledBecauseInPolicy, $disabledBecauseInPolicy,
false, false,
'', $classdisabledBecauseInPolicy,
$classdisabledBecauseInPolicy 'new-password'
); );
push_table_simple($data, 'user_pass'); push_table_simple($data, 'user_pass');

View File

@ -357,7 +357,7 @@ function addConnectionMap() {
for (var index in connectionMaps) { for (var index in connectionMaps) {
if (isInt(index)) { if (isInt(index)) {
if (connectionMaps[index] == idConnectionMap) { if (connectionMaps[index] == idConnectionMap) {
alert("<?php echo __('The connection'); ?> "' + connectionMapName + '" <?php echo __('just added previously.'); ?>"); alert("<?php echo __('The connection'); ?> " + connectionMapName + " <?php echo __('just added previously.'); ?>");
return; return;
} }

View File

@ -725,7 +725,6 @@ echo '</form>';
} }
}); });
$modulesSelect.change();
} }
var processGet = function (params, callback) { var processGet = function (params, callback) {

View File

@ -221,7 +221,7 @@ switch ($action) {
$server_name = $item['server_name']; $server_name = $item['server_name'];
// Metaconsole db connection. // Metaconsole db connection.
if ($meta && $server_name != '') { if ($meta && !empty($server_name)) {
$connection = metaconsole_get_connection($server_name); $connection = metaconsole_get_connection($server_name);
if (metaconsole_load_external_db($connection) != NOERR) { if (metaconsole_load_external_db($connection) != NOERR) {
continue; continue;
@ -547,8 +547,43 @@ switch ($action) {
break; break;
case 'event_report_agent': case 'event_report_agent':
case 'event_report_group': $description = $item['description'];
$period = $item['period'];
$group = $item['id_group'];
$recursion = $item['recursion']; $recursion = $item['recursion'];
$idAgent = $item['id_agent'];
$idAgentModule = $item['id_agent_module'];
$show_summary_group = $style['show_summary_group'];
$filter_event_severity = json_decode($style['filter_event_severity'], true);
$filter_event_status = json_decode($style['filter_event_status'], true);
$filter_event_type = json_decode($style['filter_event_type'], true);
$event_graph_by_user_validator = $style['event_graph_by_user_validator'];
$event_graph_by_criticity = $style['event_graph_by_criticity'];
$event_graph_validated_vs_unvalidated = $style['event_graph_validated_vs_unvalidated'];
$include_extended_events = $item['show_extended_events'];
$filter_search = $style['event_filter_search'];
break;
case 'event_report_group':
$description = $item['description'];
$period = $item['period'];
$group = $item['id_group'];
$recursion = $item['recursion'];
$event_graph_by_agent = $style['event_graph_by_agent'];
$event_graph_by_user_validator = $style['event_graph_by_user_validator'];
$event_graph_by_criticity = $style['event_graph_by_criticity'];
$event_graph_validated_vs_unvalidated = $style['event_graph_validated_vs_unvalidated'];
$filter_search = $style['event_filter_search'];
$include_extended_events = $item['show_extended_events']; $include_extended_events = $item['show_extended_events'];
break; break;
@ -2805,7 +2840,7 @@ function print_SLA_list($width, $action, $idItem=null)
foreach ($itemsSLA as $item) { foreach ($itemsSLA as $item) {
$server_name = $item['server_name']; $server_name = $item['server_name'];
// Metaconsole db connection. // Metaconsole db connection.
if ($meta && $server_name != '') { if ($meta && !empty($server_name)) {
$connection = metaconsole_get_connection( $connection = metaconsole_get_connection(
$server_name $server_name
); );
@ -3133,7 +3168,7 @@ function print_General_list($width, $action, $idItem=null, $type='general')
foreach ($itemsGeneral as $item) { foreach ($itemsGeneral as $item) {
$server_name = $item['server_name']; $server_name = $item['server_name'];
// Metaconsole db connection. // Metaconsole db connection.
if ($meta && $server_name != '') { if ($meta && !empty($server_name)) {
$connection = metaconsole_get_connection( $connection = metaconsole_get_connection(
$server_name $server_name
); );

View File

@ -45,6 +45,9 @@
.parent() .parent()
.addClass('checkselected'); .addClass('checkselected');
$(".check_delete").prop("checked", true); $(".check_delete").prop("checked", true);
$('.check_delete').each(function(){
$('#hidden-id_report_'+$(this).val()).prop("disabled", false);
});
} }
else{ else{
$('[id^=checkbox-massive_report_check]') $('[id^=checkbox-massive_report_check]')
@ -1345,6 +1348,8 @@ switch ($action) {
$values['description'] = get_parameter('description'); $values['description'] = get_parameter('description');
$values['type'] = get_parameter('type', null); $values['type'] = get_parameter('type', null);
$values['recursion'] = get_parameter('recursion', null); $values['recursion'] = get_parameter('recursion', null);
$values['show_extended_events'] = get_parameter('include_extended_events', null);
$label = get_parameter('label', ''); $label = get_parameter('label', '');
// Add macros name. // Add macros name.
@ -1900,8 +1905,8 @@ switch ($action) {
$style['event_graph_by_user_validator'] = $event_graph_by_user_validator; $style['event_graph_by_user_validator'] = $event_graph_by_user_validator;
$style['event_graph_by_criticity'] = $event_graph_by_criticity; $style['event_graph_by_criticity'] = $event_graph_by_criticity;
$style['event_graph_validated_vs_unvalidated'] = $event_graph_validated_vs_unvalidated; $style['event_graph_validated_vs_unvalidated'] = $event_graph_validated_vs_unvalidated;
$style['event_filter_search'] = $event_filter_search; $style['event_filter_search'] = $event_filter_search;
if ($label != '') { if ($label != '') {
$style['label'] = $label; $style['label'] = $label;
} else { } else {
@ -2007,6 +2012,7 @@ switch ($action) {
); );
$name_it = (string) get_parameter('name'); $name_it = (string) get_parameter('name');
$values['recursion'] = get_parameter('recursion', null); $values['recursion'] = get_parameter('recursion', null);
$values['show_extended_events'] = get_parameter('include_extended_events', null);
$values['name'] = reporting_label_macro( $values['name'] = reporting_label_macro(
$items_label, $items_label,
$name_it $name_it
@ -2418,6 +2424,7 @@ switch ($action) {
case 'event_report_agent': case 'event_report_agent':
case 'event_report_group': case 'event_report_group':
case 'event_report_module': case 'event_report_module':
$show_summary_group = get_parameter( $show_summary_group = get_parameter(
'show_summary_group', 'show_summary_group',
0 0
@ -2473,22 +2480,11 @@ switch ($action) {
$style['event_graph_by_user_validator'] = $event_graph_by_user_validator; $style['event_graph_by_user_validator'] = $event_graph_by_user_validator;
$style['event_graph_by_criticity'] = $event_graph_by_criticity; $style['event_graph_by_criticity'] = $event_graph_by_criticity;
$style['event_graph_validated_vs_unvalidated'] = $event_graph_validated_vs_unvalidated; $style['event_graph_validated_vs_unvalidated'] = $event_graph_validated_vs_unvalidated;
$style['event_filter_search'] = $event_filter_search;
if ($label != '') {
switch ($values['type']) { $style['label'] = $label;
case 'event_report_group': } else {
case 'event_report_agent': $style['label'] = '';
$style['event_filter_search'] = $event_filter_search;
if ($label != '') {
$style['label'] = $label;
} else {
$style['label'] = '';
}
break;
default:
// Default.
break;
} }
break; break;

View File

@ -254,7 +254,12 @@ function update_button_palette_callback() {
var values = {}; var values = {};
values = readFields(); values = readFields();
if (values["map_linked"] == 0) {
if (values["agent"] == "" || values["agent"] == "none") {
dialog_message("#message_alert_no_agent");
return false;
}
}
// TODO VALIDATE DATA // TODO VALIDATE DATA
switch (selectedItem) { switch (selectedItem) {
case "background": case "background":
@ -1260,6 +1265,7 @@ function create_button_palette_callback() {
dialog_message("#message_alert_max_height"); dialog_message("#message_alert_max_height");
validate = false; validate = false;
} }
break; break;
case "group_item": case "group_item":
if (values["height"] == "") { if (values["height"] == "") {
@ -1323,6 +1329,12 @@ function create_button_palette_callback() {
dialog_message("#message_alert_no_image"); dialog_message("#message_alert_no_image");
validate = false; validate = false;
} }
if (values["map_linked"] == 0) {
if (values["agent"] == "" || values["agent"] == "none") {
dialog_message("#message_alert_no_agent");
validate = false;
}
}
break; break;
case "auto_sla_graph": case "auto_sla_graph":

View File

@ -659,18 +659,18 @@ class Wizard
if ($input['arguments']['inline'] != 'true') { if ($input['arguments']['inline'] != 'true') {
$output .= '<div class="edit_discovery_input">'; $output .= '<div class="edit_discovery_input">';
} else { } else {
$output .= '<div style="display: flex; margin-bottom: 25px;">'; $output .= '<div style="display: flex; margin-bottom: 25px; flex-wrap: wrap;">';
if (!isset($input['extra'])) { if (!isset($input['extra'])) {
$output .= '<div style="width: 50%;">'; $output .= '<div style="width: 50%;">';
} }
if (isset($input['extra'])) { if (isset($input['extra'])) {
$output .= '<div style="width: 50%; display: flex;">'; $output .= '<div style="display: flex; margin-right:10px;">';
} }
} }
if ($input['arguments']['inline'] == 'true' && isset($input['extra'])) { if ($input['arguments']['inline'] == 'true' && isset($input['extra'])) {
$output .= '<div style="width: 50%">'; $output .= '<div style="margin-right:10px;">';
} }
$output .= '<div class="label_select">'; $output .= '<div class="label_select">';
@ -690,11 +690,11 @@ class Wizard
$output .= $this->printInput($input['arguments']); $output .= $this->printInput($input['arguments']);
$output .= '</div>'; $output .= '</div>';
} else if ($input['arguments']['inline'] == 'true') { } else if ($input['arguments']['inline'] == 'true') {
$output .= '<div style="width: 50%;">';
if (isset($input['extra'])) { if (isset($input['extra'])) {
$output .= '<div style="float: center;">'; $output .= '<div style="">';
$output .= '<div style="float: left;">';
} else { } else {
$output .= '<div style="width:50%;">';
$output .= '<div style="float: right;">'; $output .= '<div style="float: right;">';
} }

View File

@ -299,6 +299,7 @@ if (check_login()) {
'status' => "<div id='reload_status_agent_".$values['id_tmetaconsole_setup'].'_'.$values['id_tagente']."'>".$image_status.'</div>', 'status' => "<div id='reload_status_agent_".$values['id_tmetaconsole_setup'].'_'.$values['id_tagente']."'>".$image_status.'</div>',
'id_agent' => $values['id_tagente'], 'id_agent' => $values['id_tagente'],
'id_server' => $values['id_tmetaconsole_setup'], 'id_server' => $values['id_tmetaconsole_setup'],
'status_value' => $values['status'],
]; ];
} }

View File

@ -1472,7 +1472,10 @@ function local_ldap_search($ldap_host, $ldap_port=389, $ldap_version=3, $dn, $ac
$tls = ' -ZZ '; $tls = ' -ZZ ';
} }
if (stripos($ldap_host, 'ldap') !== false) { if (stripos($ldap_host, 'ldap://') !== false
|| stripos($ldap_host, 'ldaps://') !== false
|| stripos($ldap_host, 'ldapi://') !== false
) {
$ldap_host = ' -H '.$ldap_host.':'.$ldap_port; $ldap_host = ' -H '.$ldap_host.':'.$ldap_port;
} else { } else {
$ldap_host = ' -h '.$ldap_host.' -p '.$ldap_port; $ldap_host = ' -h '.$ldap_host.' -p '.$ldap_port;

View File

@ -72,6 +72,8 @@ class TreeService extends Tree
protected function getFirstLevel() protected function getFirstLevel()
{ {
global $config;
$processed_items = $this->getProcessedServices(); $processed_items = $this->getProcessedServices();
$ids = array_keys($processed_items); $ids = array_keys($processed_items);

View File

@ -20,7 +20,7 @@
/** /**
* Pandora build version and version * Pandora build version and version
*/ */
$build_version = 'PC190610'; $build_version = 'PC190617';
$pandora_version = 'v7.0NG.735'; $pandora_version = 'v7.0NG.735';
// Do not overwrite default timezone set if defined. // Do not overwrite default timezone set if defined.

View File

@ -11519,7 +11519,7 @@ function api_set_create_event($id, $trash1, $other, $returnType)
if ($other['data'][18] != '') { if ($other['data'][18] != '') {
$values['id_extra'] = $other['data'][18]; $values['id_extra'] = $other['data'][18];
$sql_validation = 'SELECT id_evento FROM tevento where estado=0 and id_extra ="'.$other['data'][18].'";'; $sql_validation = 'SELECT id_evento FROM tevento where estado IN (0,2) and id_extra ="'.$other['data'][18].'";';
$validation = db_get_all_rows_sql($sql_validation); $validation = db_get_all_rows_sql($sql_validation);
if ($validation) { if ($validation) {
foreach ($validation as $val) { foreach ($validation as $val) {

View File

@ -180,7 +180,7 @@ function config_update_config()
$error_update[] = __('Automatic check for updates'); $error_update[] = __('Automatic check for updates');
} }
if (!config_update_value('cert_path', (bool) get_parameter('cert_path'))) { if (!config_update_value('cert_path', get_parameter('cert_path'))) {
$error_update[] = __('SSL cert path'); $error_update[] = __('SSL cert path');
} }
@ -2167,9 +2167,9 @@ function config_process_config()
if (!isset($config['ad_adv_perms'])) { if (!isset($config['ad_adv_perms'])) {
config_update_value('ad_adv_perms', ''); config_update_value('ad_adv_perms', '');
} else { } else {
$temp_ad_adv_perms = [];
if (!json_decode(io_safe_output($config['ad_adv_perms']))) { if (!json_decode(io_safe_output($config['ad_adv_perms']))) {
$temp_ad_adv_perms = []; if ($config['ad_adv_perms'] != '') {
if (!isset($config['ad_adv_perms']) && $config['ad_adv_perms'] != '') {
$perms = explode(';', io_safe_output($config['ad_adv_perms'])); $perms = explode(';', io_safe_output($config['ad_adv_perms']));
foreach ($perms as $ad_adv_perm) { foreach ($perms as $ad_adv_perm) {
if (preg_match('/[\[\]]/', $ad_adv_perm)) { if (preg_match('/[\[\]]/', $ad_adv_perm)) {
@ -2232,22 +2232,26 @@ function config_process_config()
if (!empty($new_ad_adv_perms)) { if (!empty($new_ad_adv_perms)) {
$temp_ad_adv_perms = json_encode($new_ad_adv_perms); $temp_ad_adv_perms = json_encode($new_ad_adv_perms);
} }
} else {
$temp_ad_adv_perms = '';
} }
} else {
config_update_value('ad_adv_perms', $temp_ad_adv_perms); $temp_ad_adv_perms = $config['ad_adv_perms'];
} }
config_update_value('ad_adv_perms', $temp_ad_adv_perms);
} }
if (!isset($config['ldap_adv_perms'])) { if (!isset($config['ldap_adv_perms'])) {
config_update_value('ldap_adv_perms', ''); config_update_value('ldap_adv_perms', '');
} else { } else {
$temp_ldap_adv_perms = [];
if (!json_decode(io_safe_output($config['ldap_adv_perms']))) { if (!json_decode(io_safe_output($config['ldap_adv_perms']))) {
$temp_ldap_adv_perms = []; if ($config['ldap_adv_perms'] != '') {
if (!isset($config['ad_adv_perms']) && $config['ldap_adv_perms'] != '') {
$perms = explode(';', io_safe_output($config['ldap_adv_perms'])); $perms = explode(';', io_safe_output($config['ldap_adv_perms']));
foreach ($perms as $ad_adv_perm) { foreach ($perms as $ldap_adv_perm) {
if (preg_match('/[\[\]]/', $ad_adv_perm)) { if (preg_match('/[\[\]]/', $ldap_adv_perm)) {
$all_data = explode(',', io_safe_output($ad_adv_perm)); $all_data = explode(',', io_safe_output($ldap_adv_perm));
$profile = $all_data[0]; $profile = $all_data[0];
$group_pnd = $all_data[1]; $group_pnd = $all_data[1];
$groups_ad = str_replace(['[', ']'], '', $all_data[2]); $groups_ad = str_replace(['[', ']'], '', $all_data[2]);
@ -2277,7 +2281,7 @@ function config_process_config()
'groups_ldap' => $groups_ldap, 'groups_ldap' => $groups_ldap,
]; ];
} else { } else {
$all_data = explode(',', io_safe_output($ad_adv_perm)); $all_data = explode(',', io_safe_output($ldap_adv_perm));
$profile = $all_data[0]; $profile = $all_data[0];
$group_pnd = $all_data[1]; $group_pnd = $all_data[1];
$groups_ad = $all_data[2]; $groups_ad = $all_data[2];
@ -2306,10 +2310,14 @@ function config_process_config()
if (!empty($new_ldap_adv_perms)) { if (!empty($new_ldap_adv_perms)) {
$temp_ldap_adv_perms = json_encode($new_ldap_adv_perms); $temp_ldap_adv_perms = json_encode($new_ldap_adv_perms);
} }
} else {
$temp_ldap_adv_perms = '';
} }
} else {
config_update_value('ldap_adv_perms', $temp_ldap_adv_perms); $temp_ldap_adv_perms = $config['ldap_adv_perms'];
} }
config_update_value('ldap_adv_perms', $temp_ldap_adv_perms);
} }
if (!isset($config['rpandora_server'])) { if (!isset($config['rpandora_server'])) {

View File

@ -188,10 +188,16 @@ function get_custom_fields_data($custom_field_name)
} }
$array_result = []; $array_result = [];
if (isset($result_meta) && is_array($result_meta)) { if (isset($result_meta) === true
&& is_array($result_meta) === true
) {
foreach ($result_meta as $result) { foreach ($result_meta as $result) {
foreach ($result as $k => $v) { if (isset($result) === true
$array_result[$v['description']] = $v['description']; && is_array($result) === true
) {
foreach ($result as $k => $v) {
$array_result[$v['description']] = $v['description'];
}
} }
} }
} }
@ -385,9 +391,13 @@ function agent_counters_custom_fields($filters)
// Filter custom data. // Filter custom data.
$custom_data_and = ''; $custom_data_and = '';
if (!in_array(-1, $filters['id_custom_fields_data'])) { if (isset($filters['id_custom_fields_data']) === true
$custom_data_array = implode("', '", $filters['id_custom_fields_data']); && is_array($filters['id_custom_fields_data']) === true
$custom_data_and = "AND tcd.description IN ('".$custom_data_array."')"; ) {
if (!in_array(-1, $filters['id_custom_fields_data'])) {
$custom_data_array = implode("', '", $filters['id_custom_fields_data']);
$custom_data_and = "AND tcd.description IN ('".$custom_data_array."')";
}
} }
// Filter custom name. // Filter custom name.
@ -693,3 +703,123 @@ function print_counters_cfv(
$html_result .= '</form>'; $html_result .= '</form>';
return $html_result; return $html_result;
} }
/**
* Function for export a csv file from Custom Fields View
*
* @param array $filters Status counters for agents and modules.
* @param array $id_status Agent status.
* @param array $module_status Module status.
*
* @return array Returns the data that will be saved in the csv file
*/
function export_custom_fields_csv($filters, $id_status, $module_status)
{
$data = agent_counters_custom_fields($filters);
$indexed_descriptions = $data['indexed_descriptions'];
// Table temporary for save array in table
// by order and search custom_field data.
$table_temporary = 'CREATE TEMPORARY TABLE temp_custom_fields (
id_server int(10),
id_agent int(10),
name_custom_fields varchar(2048),
critical_count int,
warning_count int,
unknown_count int,
notinit_count int,
normal_count int,
total_count int,
`status` int(2),
KEY `data_index_temp_1` (`id_server`, `id_agent`)
)';
db_process_sql($table_temporary);
// Insert values array in table temporary.
$values_insert = [];
foreach ($indexed_descriptions as $key => $value) {
$values_insert[] = '('.$value['id_server'].', '.$value['id_agente'].", '".$value['description']."', '".$value['critical_count']."', '".$value['warning_count']."', '".$value['unknown_count']."', '".$value['notinit_count']."', '".$value['normal_count']."', '".$value['total_count']."', ".$value['status'].')';
}
$values_insert_implode = implode(',', $values_insert);
$query_insert = 'INSERT INTO temp_custom_fields VALUES '.$values_insert_implode;
db_process_sql($query_insert);
// Search for status module.
$status_agent_search = '';
if (isset($id_status) === true && is_array($id_status) === true) {
if (in_array(-1, $id_status) === false) {
if (in_array(AGENT_MODULE_STATUS_NOT_NORMAL, $id_status) === false) {
$status_agent_search = ' AND temp.status IN ('.implode(',', $id_status).')';
} else {
// Not normal statuses.
$status_agent_search = ' AND temp.status IN (1,2,3,4,5)';
}
}
}
// Search for status module.
$status_module_search = '';
if (isset($module_status) === true && is_array($module_status) === true) {
if (in_array(-1, $module_status) === false) {
if (in_array(AGENT_MODULE_STATUS_NOT_NORMAL, $module_status) === false) {
if (count($module_status) > 0) {
$status_module_search = ' AND ( ';
foreach ($module_status as $key => $value) {
$status_module_search .= ($key != 0) ? ' OR (' : ' (';
switch ($value) {
default:
case AGENT_STATUS_NORMAL:
$status_module_search .= ' temp.normal_count > 0) ';
break;
case AGENT_STATUS_CRITICAL:
$status_module_search .= ' temp.critical_count > 0) ';
break;
case AGENT_STATUS_WARNING:
$status_module_search .= ' temp.warning_count > 0) ';
break;
case AGENT_STATUS_UNKNOWN:
$status_module_search .= ' temp.unknown_count > 0) ';
break;
case AGENT_STATUS_NOT_INIT:
$status_module_search .= ' temp.notinit_count > 0) ';
break;
}
}
$status_module_search .= ' ) ';
}
} else {
// Not normal.
$status_module_search = ' AND ( temp.critical_count > 0 OR temp.warning_count > 0 OR temp.unknown_count > 0 AND temp.notinit_count > 0 )';
}
}
}
// Query all fields result.
$query = sprintf(
'SELECT
temp.name_custom_fields,
tma.alias,
tma.direccion,
tma.server_name,
temp.status
FROM tmetaconsole_agent tma
INNER JOIN temp_custom_fields temp
ON temp.id_agent = tma.id_tagente
AND temp.id_server = tma.id_tmetaconsole_setup
WHERE tma.disabled = 0
%s
%s
',
$status_agent_search,
$status_module_search
);
$result = db_get_all_rows_sql($query);
return $result;
}

View File

@ -4551,7 +4551,7 @@ function events_list_events_grouped_agents($sql)
$sql = sprintf( $sql = sprintf(
'SELECT * FROM %s 'SELECT * FROM %s
LEFT JOIN tagent_secondary_group LEFT JOIN tagent_secondary_group
ON tagent_secondary_group.id_agent = tevento.id_agente ON tagent_secondary_group.id_agent = id_agente
WHERE %s', WHERE %s',
$table, $table,
$sql $sql

View File

@ -1233,7 +1233,7 @@ function html_print_extended_select_for_cron($hour='*', $minute='*', $mday='*',
* *
* @return string HTML code if return parameter is true. * @return string HTML code if return parameter is true.
*/ */
function html_print_input_text_extended($name, $value, $id, $alt, $size, $maxlength, $disabled, $script, $attributes, $return=false, $password=false, $function='') function html_print_input_text_extended($name, $value, $id, $alt, $size, $maxlength, $disabled, $script, $attributes, $return=false, $password=false, $function='', $autocomplete='off')
{ {
static $idcounter = 0; static $idcounter = 0;
@ -1283,7 +1283,7 @@ function html_print_input_text_extended($name, $value, $id, $alt, $size, $maxlen
'autocomplete', 'autocomplete',
]; ];
$output = '<input '.($password ? 'type="password" autocomplete="off" ' : 'type="text" '); $output = '<input '.($password ? 'type="password" autocomplete="'.$autocomplete.'" ' : 'type="text" ');
if ($disabled && (!is_array($attributes) || !array_key_exists('disabled', $attributes))) { if ($disabled && (!is_array($attributes) || !array_key_exists('disabled', $attributes))) {
$output .= 'readonly="readonly" '; $output .= 'readonly="readonly" ';
@ -1435,7 +1435,8 @@ function html_print_input_password(
$return=false, $return=false,
$disabled=false, $disabled=false,
$required=false, $required=false,
$class='' $class='',
$autocomplete='off'
) { ) {
if ($maxlength == 0) { if ($maxlength == 0) {
$maxlength = 255; $maxlength = 255;
@ -1454,7 +1455,7 @@ function html_print_input_password(
$attr['class'] = $class; $attr['class'] = $class;
} }
return html_print_input_text_extended($name, $value, 'password-'.$name, $alt, $size, $maxlength, $disabled, '', $attr, $return, true); return html_print_input_text_extended($name, $value, 'password-'.$name, $alt, $size, $maxlength, $disabled, '', $attr, $return, true, '', $autocomplete);
} }

View File

@ -1383,7 +1383,7 @@ function reporting_event_top_n(
foreach ($tops as $key => $row) { foreach ($tops as $key => $row) {
// Metaconsole connection. // Metaconsole connection.
$server_name = $row['server_name']; $server_name = $row['server_name'];
if (($config['metaconsole'] == 1) && $server_name != '' && defined('METACONSOLE')) { if (($config['metaconsole'] == 1) && $server_name != '' && is_metaconsole()) {
$connection = metaconsole_get_connection($server_name); $connection = metaconsole_get_connection($server_name);
if (metaconsole_load_external_db($connection) != NOERR) { if (metaconsole_load_external_db($connection) != NOERR) {
// ui_print_error_message ("Error connecting to ".$server_name); // ui_print_error_message ("Error connecting to ".$server_name);
@ -1426,7 +1426,7 @@ function reporting_event_top_n(
} }
// Restore dbconnection. // Restore dbconnection.
if (($config['metaconsole'] == 1) && $server_name != '' && defined('METACONSOLE')) { if (($config['metaconsole'] == 1) && $server_name != '' && is_metaconsole()) {
metaconsole_restore_db(); metaconsole_restore_db();
} }
} }
@ -2330,7 +2330,7 @@ function reporting_exception(
do { do {
// Metaconsole connection. // Metaconsole connection.
$server_name = $exceptions[$i]['server_name']; $server_name = $exceptions[$i]['server_name'];
if (($config['metaconsole'] == 1) && $server_name != '' && defined('METACONSOLE')) { if (($config['metaconsole'] == 1) && $server_name != '' && is_metaconsole()) {
$connection = metaconsole_get_connection($server_name); $connection = metaconsole_get_connection($server_name);
if (metaconsole_load_external_db($connection) != NOERR) { if (metaconsole_load_external_db($connection) != NOERR) {
// ui_print_error_message ("Error connecting to ".$server_name); // ui_print_error_message ("Error connecting to ".$server_name);
@ -2372,7 +2372,7 @@ function reporting_exception(
$i++; $i++;
// Restore dbconnection. // Restore dbconnection.
if (($config['metaconsole'] == 1) && $server_name != '' && defined('METACONSOLE')) { if (($config['metaconsole'] == 1) && $server_name != '' && is_metaconsole()) {
metaconsole_restore_db(); metaconsole_restore_db();
} }
} while ($min === false && $i < count($exceptions)); } while ($min === false && $i < count($exceptions));
@ -2385,7 +2385,7 @@ function reporting_exception(
foreach ($exceptions as $exc) { foreach ($exceptions as $exc) {
// Metaconsole connection. // Metaconsole connection.
$server_name = $exc['server_name']; $server_name = $exc['server_name'];
if (($config['metaconsole'] == 1) && $server_name != '' && defined('METACONSOLE')) { if (($config['metaconsole'] == 1) && $server_name != '' && is_metaconsole()) {
$connection = metaconsole_get_connection($server_name); $connection = metaconsole_get_connection($server_name);
if (metaconsole_load_external_db($connection) != NOERR) { if (metaconsole_load_external_db($connection) != NOERR) {
// ui_print_error_message ("Error connecting to ".$server_name); // ui_print_error_message ("Error connecting to ".$server_name);
@ -2499,7 +2499,7 @@ function reporting_exception(
} }
// Restore dbconnection // Restore dbconnection
if (($config['metaconsole'] == 1) && $server_name != '' && defined('METACONSOLE')) { if (($config['metaconsole'] == 1) && $server_name != '' && is_metaconsole()) {
metaconsole_restore_db(); metaconsole_restore_db();
} }
} }
@ -2693,7 +2693,7 @@ function reporting_group_report($report, $content)
{ {
global $config; global $config;
$metaconsole_on = ($config['metaconsole'] == 1) && defined('METACONSOLE'); $metaconsole_on = ($config['metaconsole'] == 1) && is_metaconsole();
$return['type'] = 'group_report'; $return['type'] = 'group_report';
@ -6173,7 +6173,7 @@ function reporting_availability($report, $content, $date=false, $time=false)
foreach ($items as $item) { foreach ($items as $item) {
// aaMetaconsole connection // aaMetaconsole connection
$server_name = $item['server_name']; $server_name = $item['server_name'];
if (($config['metaconsole'] == 1) && $server_name != '' && defined('METACONSOLE')) { if (($config['metaconsole'] == 1) && $server_name != '' && is_metaconsole()) {
$connection = metaconsole_get_connection($server_name); $connection = metaconsole_get_connection($server_name);
if (metaconsole_load_external_db($connection) != NOERR) { if (metaconsole_load_external_db($connection) != NOERR) {
// ui_print_error_message ("Error connecting to ".$server_name); // ui_print_error_message ("Error connecting to ".$server_name);
@ -6185,7 +6185,7 @@ function reporting_availability($report, $content, $date=false, $time=false)
|| modules_is_not_init($item['id_agent_module']) || modules_is_not_init($item['id_agent_module'])
) { ) {
// Restore dbconnection // Restore dbconnection
if (($config['metaconsole'] == 1) && $server_name != '' && defined('METACONSOLE')) { if (($config['metaconsole'] == 1) && $server_name != '' && is_metaconsole()) {
metaconsole_restore_db(); metaconsole_restore_db();
} }
@ -6242,7 +6242,7 @@ function reporting_availability($report, $content, $date=false, $time=false)
$text = $row['data']['agent'].' ('.$text.')'; $text = $row['data']['agent'].' ('.$text.')';
// Restore dbconnection // Restore dbconnection
if (($config['metaconsole'] == 1) && $server_name != '' && defined('METACONSOLE')) { if (($config['metaconsole'] == 1) && $server_name != '' && is_metaconsole()) {
metaconsole_restore_db(); metaconsole_restore_db();
} }
@ -6807,7 +6807,7 @@ function reporting_increment($report, $content)
$return['data'] = []; $return['data'] = [];
if (defined('METACONSOLE')) { if (is_metaconsole()) {
$sql1 = 'SELECT datos FROM tagente_datos WHERE id_agente_modulo = '.$id_agent_module.' $sql1 = 'SELECT datos FROM tagente_datos WHERE id_agente_modulo = '.$id_agent_module.'
AND utimestamp <= '.(time() - $period).' ORDER BY utimestamp DESC'; AND utimestamp <= '.(time() - $period).' ORDER BY utimestamp DESC';
$sql2 = 'SELECT datos FROM tagente_datos WHERE id_agente_modulo = '.$id_agent_module.' ORDER BY utimestamp DESC'; $sql2 = 'SELECT datos FROM tagente_datos WHERE id_agente_modulo = '.$id_agent_module.' ORDER BY utimestamp DESC';
@ -6845,7 +6845,7 @@ function reporting_increment($report, $content)
$last_data = db_get_value_sql('SELECT datos FROM tagente_datos WHERE id_agente_modulo = '.$id_agent_module.' ORDER BY utimestamp DESC'); $last_data = db_get_value_sql('SELECT datos FROM tagente_datos WHERE id_agente_modulo = '.$id_agent_module.' ORDER BY utimestamp DESC');
} }
if (!defined('METACONSOLE')) { if (!is_metaconsole()) {
} }
if ($old_data === false || $last_data === false) { if ($old_data === false || $last_data === false) {
@ -6934,7 +6934,7 @@ function reporting_general($report, $content)
foreach ($generals as $row) { foreach ($generals as $row) {
// Metaconsole connection // Metaconsole connection
$server_name = $row['server_name']; $server_name = $row['server_name'];
if (($config['metaconsole'] == 1) && $server_name != '' && defined('METACONSOLE')) { if (($config['metaconsole'] == 1) && $server_name != '' && is_metaconsole()) {
$connection = metaconsole_get_connection($server_name); $connection = metaconsole_get_connection($server_name);
if (metaconsole_load_external_db($connection) != NOERR) { if (metaconsole_load_external_db($connection) != NOERR) {
// ui_print_error_message ("Error connecting to ".$server_name); // ui_print_error_message ("Error connecting to ".$server_name);
@ -7085,7 +7085,7 @@ function reporting_general($report, $content)
$i++; $i++;
// Restore dbconnection // Restore dbconnection
if (($config['metaconsole'] == 1) && $server_name != '' && defined('METACONSOLE')) { if (($config['metaconsole'] == 1) && $server_name != '' && is_metaconsole()) {
metaconsole_restore_db(); metaconsole_restore_db();
} }
} }

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,45 @@
/*!
Buttons for DataTables 1.5.6
©2016-2019 SpryMedia Ltd - datatables.net/license
*/
var $jscomp=$jscomp||{};$jscomp.scope={};$jscomp.findInternal=function(d,q,n){d instanceof String&&(d=String(d));for(var l=d.length,u=0;u<l;u++){var p=d[u];if(q.call(n,p,u,d))return{i:u,v:p}}return{i:-1,v:void 0}};$jscomp.ASSUME_ES5=!1;$jscomp.ASSUME_NO_NATIVE_MAP=!1;$jscomp.ASSUME_NO_NATIVE_SET=!1;$jscomp.SIMPLE_FROUND_POLYFILL=!1;
$jscomp.defineProperty=$jscomp.ASSUME_ES5||"function"==typeof Object.defineProperties?Object.defineProperty:function(d,q,n){d!=Array.prototype&&d!=Object.prototype&&(d[q]=n.value)};$jscomp.getGlobal=function(d){return"undefined"!=typeof window&&window===d?d:"undefined"!=typeof global&&null!=global?global:d};$jscomp.global=$jscomp.getGlobal(this);
$jscomp.polyfill=function(d,q,n,l){if(q){n=$jscomp.global;d=d.split(".");for(l=0;l<d.length-1;l++){var u=d[l];u in n||(n[u]={});n=n[u]}d=d[d.length-1];l=n[d];q=q(l);q!=l&&null!=q&&$jscomp.defineProperty(n,d,{configurable:!0,writable:!0,value:q})}};$jscomp.polyfill("Array.prototype.find",function(d){return d?d:function(d,n){return $jscomp.findInternal(this,d,n).v}},"es6","es3");
(function(d){"function"===typeof define&&define.amd?define(["jquery","datatables.net"],function(q){return d(q,window,document)}):"object"===typeof exports?module.exports=function(q,n){q||(q=window);n&&n.fn.dataTable||(n=require("datatables.net")(q,n).$);return d(n,q,q.document)}:d(jQuery,window,document)})(function(d,q,n,l){function u(a){a=new p.Api(a);var b=a.init().buttons||p.defaults.buttons;return(new t(a,b)).container()}var p=d.fn.dataTable,B=0,C=0,r=p.ext.buttons,t=function(a,b){if(!(this instanceof
t))return function(b){return(new t(b,a)).container()};"undefined"===typeof b&&(b={});!0===b&&(b={});d.isArray(b)&&(b={buttons:b});this.c=d.extend(!0,{},t.defaults,b);b.buttons&&(this.c.buttons=b.buttons);this.s={dt:new p.Api(a),buttons:[],listenKeys:"",namespace:"dtb"+B++};this.dom={container:d("<"+this.c.dom.container.tag+"/>").addClass(this.c.dom.container.className)};this._constructor()};d.extend(t.prototype,{action:function(a,b){a=this._nodeToButton(a);if(b===l)return a.conf.action;a.conf.action=
b;return this},active:function(a,b){var c=this._nodeToButton(a);a=this.c.dom.button.active;c=d(c.node);if(b===l)return c.hasClass(a);c.toggleClass(a,b===l?!0:b);return this},add:function(a,b){var c=this.s.buttons;if("string"===typeof b){b=b.split("-");c=this.s;for(var d=0,f=b.length-1;d<f;d++)c=c.buttons[1*b[d]];c=c.buttons;b=1*b[b.length-1]}this._expandButton(c,a,!1,b);this._draw();return this},container:function(){return this.dom.container},disable:function(a){a=this._nodeToButton(a);d(a.node).addClass(this.c.dom.button.disabled);
return this},destroy:function(){d("body").off("keyup."+this.s.namespace);var a=this.s.buttons.slice(),b;var c=0;for(b=a.length;c<b;c++)this.remove(a[c].node);this.dom.container.remove();a=this.s.dt.settings()[0];c=0;for(b=a.length;c<b;c++)if(a.inst===this){a.splice(c,1);break}return this},enable:function(a,b){if(!1===b)return this.disable(a);a=this._nodeToButton(a);d(a.node).removeClass(this.c.dom.button.disabled);return this},name:function(){return this.c.name},node:function(a){if(!a)return this.dom.container;
a=this._nodeToButton(a);return d(a.node)},processing:function(a,b){a=this._nodeToButton(a);if(b===l)return d(a.node).hasClass("processing");d(a.node).toggleClass("processing",b);return this},remove:function(a){var b=this._nodeToButton(a),c=this._nodeToHost(a),e=this.s.dt;if(b.buttons.length)for(var f=b.buttons.length-1;0<=f;f--)this.remove(b.buttons[f].node);b.conf.destroy&&b.conf.destroy.call(e.button(a),e,d(a),b.conf);this._removeKey(b.conf);d(b.node).remove();a=d.inArray(b,c);c.splice(a,1);return this},
text:function(a,b){var c=this._nodeToButton(a);a=this.c.dom.collection.buttonLiner;a=c.inCollection&&a&&a.tag?a.tag:this.c.dom.buttonLiner.tag;var e=this.s.dt,f=d(c.node),g=function(a){return"function"===typeof a?a(e,f,c.conf):a};if(b===l)return g(c.conf.text);c.conf.text=b;a?f.children(a).html(g(b)):f.html(g(b));return this},_constructor:function(){var a=this,b=this.s.dt,c=b.settings()[0],e=this.c.buttons;c._buttons||(c._buttons=[]);c._buttons.push({inst:this,name:this.c.name});for(var f=0,g=e.length;f<
g;f++)this.add(e[f]);b.on("destroy",function(b,d){d===c&&a.destroy()});d("body").on("keyup."+this.s.namespace,function(b){if(!n.activeElement||n.activeElement===n.body){var c=String.fromCharCode(b.keyCode).toLowerCase();-1!==a.s.listenKeys.toLowerCase().indexOf(c)&&a._keypress(c,b)}})},_addKey:function(a){a.key&&(this.s.listenKeys+=d.isPlainObject(a.key)?a.key.key:a.key)},_draw:function(a,b){a||(a=this.dom.container,b=this.s.buttons);a.children().detach();for(var c=0,d=b.length;c<d;c++)a.append(b[c].inserter),
a.append(" "),b[c].buttons&&b[c].buttons.length&&this._draw(b[c].collection,b[c].buttons)},_expandButton:function(a,b,c,e){var f=this.s.dt,g=0;b=d.isArray(b)?b:[b];for(var h=0,k=b.length;h<k;h++){var v=this._resolveExtends(b[h]);if(v)if(d.isArray(v))this._expandButton(a,v,c,e);else{var m=this._buildButton(v,c);if(m){e!==l?(a.splice(e,0,m),e++):a.push(m);if(m.conf.buttons){var y=this.c.dom.collection;m.collection=d("<"+y.tag+"/>").addClass(y.className).attr("role","menu");m.conf._collection=m.collection;
this._expandButton(m.buttons,m.conf.buttons,!0,e)}v.init&&v.init.call(f.button(m.node),f,d(m.node),v);g++}}}},_buildButton:function(a,b){var c=this.c.dom.button,e=this.c.dom.buttonLiner,f=this.c.dom.collection,g=this.s.dt,h=function(b){return"function"===typeof b?b(g,m,a):b};b&&f.button&&(c=f.button);b&&f.buttonLiner&&(e=f.buttonLiner);if(a.available&&!a.available(g,a))return!1;var k=function(a,b,c,e){e.action.call(b.button(c),a,b,c,e);d(b.table().node()).triggerHandler("buttons-action.dt",[b.button(c),
b,c,e])};f=a.tag||c.tag;var v=a.clickBlurs===l?!0:a.clickBlurs,m=d("<"+f+"/>").addClass(c.className).attr("tabindex",this.s.dt.settings()[0].iTabIndex).attr("aria-controls",this.s.dt.table().node().id).on("click.dtb",function(b){b.preventDefault();!m.hasClass(c.disabled)&&a.action&&k(b,g,m,a);v&&m.blur()}).on("keyup.dtb",function(b){13===b.keyCode&&!m.hasClass(c.disabled)&&a.action&&k(b,g,m,a)});"a"===f.toLowerCase()&&m.attr("href","#");"button"===f.toLowerCase()&&m.attr("type","button");e.tag?(f=
d("<"+e.tag+"/>").html(h(a.text)).addClass(e.className),"a"===e.tag.toLowerCase()&&f.attr("href","#"),m.append(f)):m.html(h(a.text));!1===a.enabled&&m.addClass(c.disabled);a.className&&m.addClass(a.className);a.titleAttr&&m.attr("title",h(a.titleAttr));a.attr&&m.attr(a.attr);a.namespace||(a.namespace=".dt-button-"+C++);e=(e=this.c.dom.buttonContainer)&&e.tag?d("<"+e.tag+"/>").addClass(e.className).append(m):m;this._addKey(a);this.c.buttonCreated&&(e=this.c.buttonCreated(a,e));return{conf:a,node:m.get(0),
inserter:e,buttons:[],inCollection:b,collection:null}},_nodeToButton:function(a,b){b||(b=this.s.buttons);for(var c=0,d=b.length;c<d;c++){if(b[c].node===a)return b[c];if(b[c].buttons.length){var f=this._nodeToButton(a,b[c].buttons);if(f)return f}}},_nodeToHost:function(a,b){b||(b=this.s.buttons);for(var c=0,d=b.length;c<d;c++){if(b[c].node===a)return b;if(b[c].buttons.length){var f=this._nodeToHost(a,b[c].buttons);if(f)return f}}},_keypress:function(a,b){if(!b._buttonsHandled){var c=function(e){for(var f=
0,g=e.length;f<g;f++){var h=e[f].conf,k=e[f].node;h.key&&(h.key===a?(b._buttonsHandled=!0,d(k).click()):!d.isPlainObject(h.key)||h.key.key!==a||h.key.shiftKey&&!b.shiftKey||h.key.altKey&&!b.altKey||h.key.ctrlKey&&!b.ctrlKey||h.key.metaKey&&!b.metaKey||(b._buttonsHandled=!0,d(k).click()));e[f].buttons.length&&c(e[f].buttons)}};c(this.s.buttons)}},_removeKey:function(a){if(a.key){var b=d.isPlainObject(a.key)?a.key.key:a.key;a=this.s.listenKeys.split("");b=d.inArray(b,a);a.splice(b,1);this.s.listenKeys=
a.join("")}},_resolveExtends:function(a){var b=this.s.dt,c,e=function(c){for(var e=0;!d.isPlainObject(c)&&!d.isArray(c);){if(c===l)return;if("function"===typeof c){if(c=c(b,a),!c)return!1}else if("string"===typeof c){if(!r[c])throw"Unknown button type: "+c;c=r[c]}e++;if(30<e)throw"Buttons: Too many iterations";}return d.isArray(c)?c:d.extend({},c)};for(a=e(a);a&&a.extend;){if(!r[a.extend])throw"Cannot extend unknown button type: "+a.extend;var f=e(r[a.extend]);if(d.isArray(f))return f;if(!f)return!1;
var g=f.className;a=d.extend({},f,a);g&&a.className!==g&&(a.className=g+" "+a.className);var h=a.postfixButtons;if(h){a.buttons||(a.buttons=[]);g=0;for(c=h.length;g<c;g++)a.buttons.push(h[g]);a.postfixButtons=null}if(h=a.prefixButtons){a.buttons||(a.buttons=[]);g=0;for(c=h.length;g<c;g++)a.buttons.splice(g,0,h[g]);a.prefixButtons=null}a.extend=f.extend}return a}});t.background=function(a,b,c,e){c===l&&(c=400);e||(e=n.body);a?d("<div/>").addClass(b).css("display","none").insertAfter(e).stop().fadeIn(c):
d("div."+b).stop().fadeOut(c,function(){d(this).removeClass(b).remove()})};t.instanceSelector=function(a,b){if(!a)return d.map(b,function(a){return a.inst});var c=[],e=d.map(b,function(a){return a.name}),f=function(a){if(d.isArray(a))for(var g=0,k=a.length;g<k;g++)f(a[g]);else"string"===typeof a?-1!==a.indexOf(",")?f(a.split(",")):(a=d.inArray(d.trim(a),e),-1!==a&&c.push(b[a].inst)):"number"===typeof a&&c.push(b[a].inst)};f(a);return c};t.buttonSelector=function(a,b){for(var c=[],e=function(a,b,c){for(var d,
f,g=0,k=b.length;g<k;g++)if(d=b[g])f=c!==l?c+g:g+"",a.push({node:d.node,name:d.conf.name,idx:f}),d.buttons&&e(a,d.buttons,f+"-")},f=function(a,b){var g,h=[];e(h,b.s.buttons);var k=d.map(h,function(a){return a.node});if(d.isArray(a)||a instanceof d)for(k=0,g=a.length;k<g;k++)f(a[k],b);else if(null===a||a===l||"*"===a)for(k=0,g=h.length;k<g;k++)c.push({inst:b,node:h[k].node});else if("number"===typeof a)c.push({inst:b,node:b.s.buttons[a].node});else if("string"===typeof a)if(-1!==a.indexOf(","))for(h=
a.split(","),k=0,g=h.length;k<g;k++)f(d.trim(h[k]),b);else if(a.match(/^\d+(\-\d+)*$/))k=d.map(h,function(a){return a.idx}),c.push({inst:b,node:h[d.inArray(a,k)].node});else if(-1!==a.indexOf(":name"))for(a=a.replace(":name",""),k=0,g=h.length;k<g;k++)h[k].name===a&&c.push({inst:b,node:h[k].node});else d(k).filter(a).each(function(){c.push({inst:b,node:this})});else"object"===typeof a&&a.nodeName&&(h=d.inArray(a,k),-1!==h&&c.push({inst:b,node:k[h]}))},g=0,h=a.length;g<h;g++)f(b,a[g]);return c};t.defaults=
{buttons:["copy","excel","csv","pdf","print"],name:"main",tabIndex:0,dom:{container:{tag:"div",className:"dt-buttons"},collection:{tag:"div",className:"dt-button-collection"},button:{tag:"ActiveXObject"in q?"a":"button",className:"dt-button",active:"active",disabled:"disabled"},buttonLiner:{tag:"span",className:""}}};t.version="1.5.6";d.extend(r,{collection:{text:function(a){return a.i18n("buttons.collection","Collection")},className:"buttons-collection",init:function(a,b,c){b.attr("aria-expanded",
!1)},action:function(a,b,c,e){var f=function(){b.buttons('[aria-haspopup="true"][aria-expanded="true"]').nodes().each(function(){var a=d(this).siblings(".dt-button-collection");a.length&&a.stop().fadeOut(e.fade,function(){a.detach()});d(this).attr("aria-expanded","false")});d("div.dt-button-background").off("click.dtb-collection");t.background(!1,e.backgroundClassName,e.fade,l);d("body").off(".dtb-collection");b.off("buttons-action.b-internal")};a="true"===c.attr("aria-expanded");f();if(!a){var g=
d(c).parents("div.dt-button-collection");a=c.position();var h=d(b.table().container()),k=!1,l=c;c.attr("aria-expanded","true");g.length&&(k=d(".dt-button-collection").position(),l=g,d("body").trigger("click.dtb-collection"));l.parents("body")[0]!==n.body&&(l=n.body.lastChild);e._collection.find(".dt-button-collection-title").remove();e._collection.prepend('<div class="dt-button-collection-title">'+e.collectionTitle+"</div>");e._collection.addClass(e.collectionLayout).css("display","none").insertAfter(l).stop().fadeIn(e.fade);
g=e._collection.css("position");if(k&&"absolute"===g)e._collection.css({top:k.top,left:k.left});else if("absolute"===g){e._collection.css({top:a.top+c.outerHeight(),left:a.left});k=h.offset().top+h.height();k=a.top+c.outerHeight()+e._collection.outerHeight()-k;g=a.top-e._collection.outerHeight();var m=h.offset().top;(k>m-g||e.dropup)&&e._collection.css("top",a.top-e._collection.outerHeight()-5);e._collection.hasClass(e.rightAlignClassName)&&e._collection.css("left",a.left+c.outerWidth()-e._collection.outerWidth());
k=a.left+e._collection.outerWidth();h=h.offset().left+h.width();k>h&&e._collection.css("left",a.left-(k-h));c=c.offset().left+e._collection.outerWidth();c>d(q).width()&&e._collection.css("left",a.left-(c-d(q).width()))}else c=e._collection.height()/2,c>d(q).height()/2&&(c=d(q).height()/2),e._collection.css("marginTop",-1*c);e.background&&t.background(!0,e.backgroundClassName,e.fade,l);setTimeout(function(){d("div.dt-button-background").on("click.dtb-collection",function(){});d("body").on("click.dtb-collection",
function(a){var b=d.fn.addBack?"addBack":"andSelf";d(a.target).parents()[b]().filter(e._collection).length||f()}).on("keyup.dtb-collection",function(a){27===a.keyCode&&f()});if(e.autoClose)b.on("buttons-action.b-internal",function(){f()})},10)}},background:!0,collectionLayout:"",collectionTitle:"",backgroundClassName:"dt-button-background",rightAlignClassName:"dt-button-right",autoClose:!1,fade:400,attr:{"aria-haspopup":!0}},copy:function(a,b){if(r.copyHtml5)return"copyHtml5";if(r.copyFlash&&r.copyFlash.available(a,
b))return"copyFlash"},csv:function(a,b){if(r.csvHtml5&&r.csvHtml5.available(a,b))return"csvHtml5";if(r.csvFlash&&r.csvFlash.available(a,b))return"csvFlash"},excel:function(a,b){if(r.excelHtml5&&r.excelHtml5.available(a,b))return"excelHtml5";if(r.excelFlash&&r.excelFlash.available(a,b))return"excelFlash"},pdf:function(a,b){if(r.pdfHtml5&&r.pdfHtml5.available(a,b))return"pdfHtml5";if(r.pdfFlash&&r.pdfFlash.available(a,b))return"pdfFlash"},pageLength:function(a){a=a.settings()[0].aLengthMenu;var b=d.isArray(a[0])?
a[0]:a,c=d.isArray(a[0])?a[1]:a;return{extend:"collection",text:function(a){return a.i18n("buttons.pageLength",{"-1":"Show all rows",_:"Show %d rows"},a.page.len())},className:"buttons-page-length",autoClose:!0,buttons:d.map(b,function(a,b){return{text:c[b],className:"button-page-length",action:function(b,c){c.page.len(a).draw()},init:function(b,c,d){var e=this;c=function(){e.active(b.page.len()===a)};b.on("length.dt"+d.namespace,c);c()},destroy:function(a,b,c){a.off("length.dt"+c.namespace)}}}),
init:function(a,b,c){var d=this;a.on("length.dt"+c.namespace,function(){d.text(c.text)})},destroy:function(a,b,c){a.off("length.dt"+c.namespace)}}}});p.Api.register("buttons()",function(a,b){b===l&&(b=a,a=l);this.selector.buttonGroup=a;var c=this.iterator(!0,"table",function(c){if(c._buttons)return t.buttonSelector(t.instanceSelector(a,c._buttons),b)},!0);c._groupSelector=a;return c});p.Api.register("button()",function(a,b){a=this.buttons(a,b);1<a.length&&a.splice(1,a.length);return a});p.Api.registerPlural("buttons().active()",
"button().active()",function(a){return a===l?this.map(function(a){return a.inst.active(a.node)}):this.each(function(b){b.inst.active(b.node,a)})});p.Api.registerPlural("buttons().action()","button().action()",function(a){return a===l?this.map(function(a){return a.inst.action(a.node)}):this.each(function(b){b.inst.action(b.node,a)})});p.Api.register(["buttons().enable()","button().enable()"],function(a){return this.each(function(b){b.inst.enable(b.node,a)})});p.Api.register(["buttons().disable()",
"button().disable()"],function(){return this.each(function(a){a.inst.disable(a.node)})});p.Api.registerPlural("buttons().nodes()","button().node()",function(){var a=d();d(this.each(function(b){a=a.add(b.inst.node(b.node))}));return a});p.Api.registerPlural("buttons().processing()","button().processing()",function(a){return a===l?this.map(function(a){return a.inst.processing(a.node)}):this.each(function(b){b.inst.processing(b.node,a)})});p.Api.registerPlural("buttons().text()","button().text()",function(a){return a===
l?this.map(function(a){return a.inst.text(a.node)}):this.each(function(b){b.inst.text(b.node,a)})});p.Api.registerPlural("buttons().trigger()","button().trigger()",function(){return this.each(function(a){a.inst.node(a.node).trigger("click")})});p.Api.registerPlural("buttons().containers()","buttons().container()",function(){var a=d(),b=this._groupSelector;this.iterator(!0,"table",function(c){if(c._buttons){c=t.instanceSelector(b,c._buttons);for(var d=0,f=c.length;d<f;d++)a=a.add(c[d].container())}});
return a});p.Api.register("button().add()",function(a,b){var c=this.context;c.length&&(c=t.instanceSelector(this._groupSelector,c[0]._buttons),c.length&&c[0].add(b,a));return this.button(this._groupSelector,a)});p.Api.register("buttons().destroy()",function(){this.pluck("inst").unique().each(function(a){a.destroy()});return this});p.Api.registerPlural("buttons().remove()","buttons().remove()",function(){this.each(function(a){a.inst.remove(a.node)});return this});var w;p.Api.register("buttons.info()",
function(a,b,c){var e=this;if(!1===a)return d("#datatables_buttons_info").fadeOut(function(){d(this).remove()}),clearTimeout(w),w=null,this;w&&clearTimeout(w);d("#datatables_buttons_info").length&&d("#datatables_buttons_info").remove();a=a?"<h2>"+a+"</h2>":"";d('<div id="datatables_buttons_info" class="dt-button-info"/>').html(a).append(d("<div/>")["string"===typeof b?"html":"append"](b)).css("display","none").appendTo("body").fadeIn();c!==l&&0!==c&&(w=setTimeout(function(){e.buttons.info(!1)},c));
return this});p.Api.register("buttons.exportData()",function(a){if(this.context.length)return D(new p.Api(this.context[0]),a)});p.Api.register("buttons.exportInfo()",function(a){a||(a={});var b=a;var c="*"===b.filename&&"*"!==b.title&&b.title!==l&&null!==b.title&&""!==b.title?b.title:b.filename;"function"===typeof c&&(c=c());c===l||null===c?c=null:(-1!==c.indexOf("*")&&(c=d.trim(c.replace("*",d("head > title").text()))),c=c.replace(/[^a-zA-Z0-9_\u00A1-\uFFFF\.,\-_ !\(\)]/g,""),(b=x(b.extension))||
(b=""),c+=b);b=x(a.title);b=null===b?null:-1!==b.indexOf("*")?b.replace("*",d("head > title").text()||"Exported data"):b;return{filename:c,title:b,messageTop:z(this,a.message||a.messageTop,"top"),messageBottom:z(this,a.messageBottom,"bottom")}});var x=function(a){return null===a||a===l?null:"function"===typeof a?a():a},z=function(a,b,c){b=x(b);if(null===b)return null;a=d("caption",a.table().container()).eq(0);return"*"===b?a.css("caption-side")!==c?null:a.length?a.text():"":b},A=d("<textarea/>")[0],
D=function(a,b){var c=d.extend(!0,{},{rows:null,columns:"",modifier:{search:"applied",order:"applied"},orthogonal:"display",stripHtml:!0,stripNewlines:!0,decodeEntities:!0,trim:!0,format:{header:function(a){return e(a)},footer:function(a){return e(a)},body:function(a){return e(a)}},customizeData:null},b),e=function(a){if("string"!==typeof a)return a;a=a.replace(/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi,"");a=a.replace(/<!\-\-.*?\-\->/g,"");c.stripHtml&&(a=a.replace(/<[^>]*>/g,""));c.trim&&
(a=a.replace(/^\s+|\s+$/g,""));c.stripNewlines&&(a=a.replace(/\n/g," "));c.decodeEntities&&(A.innerHTML=a,a=A.value);return a};b=a.columns(c.columns).indexes().map(function(b){var d=a.column(b).header();return c.format.header(d.innerHTML,b,d)}).toArray();var f=a.table().footer()?a.columns(c.columns).indexes().map(function(b){var d=a.column(b).footer();return c.format.footer(d?d.innerHTML:"",b,d)}).toArray():null,g=d.extend({},c.modifier);a.select&&"function"===typeof a.select.info&&g.selected===l&&
a.rows(c.rows,d.extend({selected:!0},g)).any()&&d.extend(g,{selected:!0});g=a.rows(c.rows,g).indexes().toArray();var h=a.cells(g,c.columns);g=h.render(c.orthogonal).toArray();h=h.nodes().toArray();for(var k=b.length,p=[],m=0,n=0,q=0<k?g.length/k:0;n<q;n++){for(var t=[k],r=0;r<k;r++)t[r]=c.format.body(g[m],n,r,h[m]),m++;p[n]=t}b={header:b,footer:f,body:p};c.customizeData&&c.customizeData(b);return b};d.fn.dataTable.Buttons=t;d.fn.DataTable.Buttons=t;d(n).on("init.dt plugin-init.dt",function(a,b){"dt"===
a.namespace&&(a=b.oInit.buttons||p.defaults.buttons)&&!b._buttons&&(new t(b,a)).container()});p.ext.feature.push({fnInit:u,cFeature:"B"});p.ext.features&&p.ext.features.register("buttons",u);return t});

View File

@ -67,6 +67,13 @@ function createVisualConsole(
? JSON.parse(data.items) ? JSON.parse(data.items)
: data.items; : data.items;
// Add the datetime when the item was received.
var receivedAt = new Date();
items.map(function(item) {
item["receivedAt"] = receivedAt;
return item;
});
var prevProps = visualConsole.props; var prevProps = visualConsole.props;
// Update the data structure. // Update the data structure.
visualConsole.props = props; visualConsole.props = props;

View File

@ -319,7 +319,7 @@ final class Container extends Model
// Default filter. // Default filter.
$filter = ['id_layout' => $layoutId]; $filter = ['id_layout' => $layoutId];
$fields = [ $fields = [
'id', 'DISTINCT(id) AS id',
'type', 'type',
'cache_expiration', 'cache_expiration',
'id_layout', 'id_layout',
@ -340,8 +340,9 @@ final class Container extends Model
// Only true condition if type is GROUP_ITEM. // Only true condition if type is GROUP_ITEM.
$filter[] = '('.\db_format_array_where_clause_sql( $filter[] = '('.\db_format_array_where_clause_sql(
[ [
'type' => GROUP_ITEM, 'id_layout' => $layoutId,
'id_group' => $groupsFilter, 'type' => GROUP_ITEM,
'id_group' => $groupsFilter,
] ]
).')'; ).')';
} }

View File

@ -207,11 +207,7 @@ final class ModuleGraph extends Item
// Custom graph. // Custom graph.
if (empty($customGraphId) === false) { if (empty($customGraphId) === false) {
$customGraph = \db_get_row_filter( $customGraph = \db_get_row('tgraph', 'id_graph', $customGraphId);
'tgraph',
'id_graph',
$customGraphId
);
$params = [ $params = [
'period' => $period, 'period' => $period,

File diff suppressed because one or more lines are too long

View File

@ -813,6 +813,15 @@ input.datos {
* - VISUAL MAPS - * - VISUAL MAPS -
* --------------------------------------------------------------------- * ---------------------------------------------------------------------
*/ */
.visual-console-edit-controls {
display: flex;
justify-content: flex-end;
}
.visual-console-edit-controls > span {
margin: 4px;
}
input.vs_button_ghost { input.vs_button_ghost {
background-color: transparent !important; background-color: transparent !important;
border: 1px solid #82b92e; border: 1px solid #82b92e;

View File

@ -25,6 +25,12 @@
user-select: text; user-select: text;
} }
.visual-console-item.is-editing {
border: 2px dashed #33ccff;
-webkit-transform: translateX(-2px) translateY(-2px);
transform: translateX(-2px) translateY(-2px);
}
@font-face { @font-face {
font-family: Alarm Clock; font-family: Alarm Clock;
src: url(alarm-clock.ttf); src: url(alarm-clock.ttf);

View File

@ -1 +1 @@
{"version":3,"sources":["webpack:///main.css","webpack:///styles.css"],"names":[],"mappings":"AAAA;EACE,gBAAgB;EAChB,kBAAkB;EAClB,4BAA4B;EAC5B,0BAA0B;EAC1B,2BAA2B;AAC7B;;AAEA;EACE,kBAAkB;EAClB,oBAAa;EAAb,oBAAa;EAAb,aAAa;EACb,2BAAuB;EAAvB,8BAAuB;MAAvB,2BAAuB;UAAvB,uBAAuB;EACvB,qBAAqB;EACrB,yBAAmB;MAAnB,sBAAmB;UAAnB,mBAAmB;EACnB,yBAAiB;KAAjB,sBAAiB;MAAjB,qBAAiB;UAAjB,iBAAiB;AACnB;;ACfA;EACE,wBAAwB;EACxB,0BAA2B;AAC7B;;AAEA,kBAAkB;;AAElB;EACE,oBAAa;EAAb,oBAAa;EAAb,aAAa;EACb,4BAAsB;EAAtB,6BAAsB;MAAtB,0BAAsB;UAAtB,sBAAsB;EACtB,wBAAuB;MAAvB,qBAAuB;UAAvB,uBAAuB;EACvB,qBAAqB;EACrB,0BAAqB;MAArB,qBAAqB;EACrB,yBAAmB;MAAnB,sBAAmB;UAAnB,mBAAmB;AACrB;;AAEA;EACE,6DAA6D;EAC7D,eAAe;;EAEf,0BAA0B;EAC1B,mCAAmC;EACnC,kCAAkC;EAClC,kCAAkC;EAClC,wCAAwC;AAC1C;;AAEA;EACE,eAAe;AACjB;;AAEA;EACE,eAAe;AACjB;;AAEA,iBAAiB;;AAEjB;EACE,kBAAkB;AACpB;;AAEA;EACE,qDAA6C;UAA7C,6CAA6C;AAC/C;;AAEA;EACE,sDAA8C;UAA9C,8CAA8C;AAChD;;AAEA;EACE,oDAA4C;UAA5C,4CAA4C;AAC9C","file":"vc.main.css","sourcesContent":["#visual-console-container {\n margin: 0px auto;\n position: relative;\n background-repeat: no-repeat;\n background-size: 100% 100%;\n background-position: center;\n}\n\n.visual-console-item {\n position: absolute;\n display: flex;\n flex-direction: initial;\n justify-items: center;\n align-items: center;\n user-select: text;\n}\n","@font-face {\n font-family: Alarm Clock;\n src: url(./alarm-clock.ttf);\n}\n\n/* Digital clock */\n\n.visual-console-item .digital-clock {\n display: flex;\n flex-direction: column;\n justify-content: center;\n justify-items: center;\n align-content: center;\n align-items: center;\n}\n\n.visual-console-item .digital-clock > span {\n font-family: \"Alarm Clock\", \"Courier New\", Courier, monospace;\n font-size: 50px;\n\n /* To improve legibility */\n -webkit-font-smoothing: antialiased;\n -moz-osx-font-smoothing: grayscale;\n text-rendering: optimizeLegibility;\n text-shadow: rgba(0, 0, 0, 0.01) 0 0 1px;\n}\n\n.visual-console-item .digital-clock > span.date {\n font-size: 25px;\n}\n\n.visual-console-item .digital-clock > span.timezone {\n font-size: 25px;\n}\n\n/* Analog clock */\n\n.visual-console-item .analogic-clock {\n text-align: center;\n}\n\n.visual-console-item .analogic-clock .hour-hand {\n animation: rotate-hour 43200s infinite linear;\n}\n\n.visual-console-item .analogic-clock .minute-hand {\n animation: rotate-minute 3600s infinite linear;\n}\n\n.visual-console-item .analogic-clock .second-hand {\n animation: rotate-second 60s infinite linear;\n}\n"],"sourceRoot":""} {"version":3,"sources":["webpack:///main.css","webpack:///styles.css"],"names":[],"mappings":"AAAA;EACE,gBAAgB;EAChB,kBAAkB;EAClB,4BAA4B;EAC5B,0BAA0B;EAC1B,2BAA2B;AAC7B;;AAEA;EACE,kBAAkB;EAClB,oBAAa;EAAb,oBAAa;EAAb,aAAa;EACb,2BAAuB;EAAvB,8BAAuB;MAAvB,2BAAuB;UAAvB,uBAAuB;EACvB,qBAAqB;EACrB,yBAAmB;MAAnB,sBAAmB;UAAnB,mBAAmB;EACnB,yBAAiB;KAAjB,sBAAiB;MAAjB,qBAAiB;UAAjB,iBAAiB;AACnB;;AAEA;EACE,0BAA0B;EAC1B,oDAA4C;UAA5C,4CAA4C;AAC9C;;ACpBA;EACE,wBAAwB;EACxB,0BAA2B;AAC7B;;AAEA,kBAAkB;;AAElB;EACE,oBAAa;EAAb,oBAAa;EAAb,aAAa;EACb,4BAAsB;EAAtB,6BAAsB;MAAtB,0BAAsB;UAAtB,sBAAsB;EACtB,wBAAuB;MAAvB,qBAAuB;UAAvB,uBAAuB;EACvB,qBAAqB;EACrB,0BAAqB;MAArB,qBAAqB;EACrB,yBAAmB;MAAnB,sBAAmB;UAAnB,mBAAmB;AACrB;;AAEA;EACE,6DAA6D;EAC7D,eAAe;;EAEf,0BAA0B;EAC1B,mCAAmC;EACnC,kCAAkC;EAClC,kCAAkC;EAClC,wCAAwC;AAC1C;;AAEA;EACE,eAAe;AACjB;;AAEA;EACE,eAAe;AACjB;;AAEA,iBAAiB;;AAEjB;EACE,kBAAkB;AACpB;;AAEA;EACE,qDAA6C;UAA7C,6CAA6C;AAC/C;;AAEA;EACE,sDAA8C;UAA9C,8CAA8C;AAChD;;AAEA;EACE,oDAA4C;UAA5C,4CAA4C;AAC9C","file":"vc.main.css","sourcesContent":["#visual-console-container {\n margin: 0px auto;\n position: relative;\n background-repeat: no-repeat;\n background-size: 100% 100%;\n background-position: center;\n}\n\n.visual-console-item {\n position: absolute;\n display: flex;\n flex-direction: initial;\n justify-items: center;\n align-items: center;\n user-select: text;\n}\n\n.visual-console-item.is-editing {\n border: 2px dashed #33ccff;\n transform: translateX(-2px) translateY(-2px);\n}\n","@font-face {\n font-family: Alarm Clock;\n src: url(./alarm-clock.ttf);\n}\n\n/* Digital clock */\n\n.visual-console-item .digital-clock {\n display: flex;\n flex-direction: column;\n justify-content: center;\n justify-items: center;\n align-content: center;\n align-items: center;\n}\n\n.visual-console-item .digital-clock > span {\n font-family: \"Alarm Clock\", \"Courier New\", Courier, monospace;\n font-size: 50px;\n\n /* To improve legibility */\n -webkit-font-smoothing: antialiased;\n -moz-osx-font-smoothing: grayscale;\n text-rendering: optimizeLegibility;\n text-shadow: rgba(0, 0, 0, 0.01) 0 0 1px;\n}\n\n.visual-console-item .digital-clock > span.date {\n font-size: 25px;\n}\n\n.visual-console-item .digital-clock > span.timezone {\n font-size: 25px;\n}\n\n/* Analog clock */\n\n.visual-console-item .analogic-clock {\n text-align: center;\n}\n\n.visual-console-item .analogic-clock .hour-hand {\n animation: rotate-hour 43200s infinite linear;\n}\n\n.visual-console-item .analogic-clock .minute-hand {\n animation: rotate-minute 3600s infinite linear;\n}\n\n.visual-console-item .analogic-clock .second-hand {\n animation: rotate-second 60s infinite linear;\n}\n"],"sourceRoot":""}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -129,7 +129,7 @@
<div style='height: 10px'> <div style='height: 10px'>
<?php <?php
$version = '7.0NG.735'; $version = '7.0NG.735';
$build = '190610'; $build = '190617';
$banner = "v$version Build $build"; $banner = "v$version Build $build";
error_reporting(0); error_reporting(0);

View File

@ -263,7 +263,7 @@ if ($date > $now) {
echo '<div class="module_graph_menu_dropdown"> echo '<div class="module_graph_menu_dropdown">
<div id="module_graph_menu_header" class="module_graph_menu_header"> <div id="module_graph_menu_header" class="module_graph_menu_header">
'.html_print_image('images/arrow_down_green.png', true, ['class' => 'module_graph_menu_arrow', 'float' => 'left'], false, false, true).' '.html_print_image('images/arrow_down_green.png', true, ['class' => 'module_graph_menu_arrow', 'float' => 'left'], false, false, true).'
<span>'.__('Graph configuration menu').ui_print_help_icon('graphs', true, $config['homeurl'], 'images/help_g.png', true).'</span> <span>'.__('Graph configuration menu').'</span>
'.html_print_image('images/config.png', true, ['float' => 'right'], false, false, true).' '.html_print_image('images/config.png', true, ['float' => 'right'], false, false, true).'
</div> </div>
<div class="module_graph_menu_content module_graph_menu_content_closed" style="display:none;">'.$form_table.'</div> <div class="module_graph_menu_content module_graph_menu_content_closed" style="display:none;">'.$form_table.'</div>

View File

@ -402,7 +402,7 @@ $alias = db_get_value('alias', 'tagente', 'id_agente', $id_agent);
echo '<div class="module_graph_menu_dropdown"> echo '<div class="module_graph_menu_dropdown">
<div id="module_graph_menu_header" class="module_graph_menu_header"> <div id="module_graph_menu_header" class="module_graph_menu_header">
'.html_print_image('images/arrow_down_green.png', true, ['class' => 'module_graph_menu_arrow', 'float' => 'left'], false, false, true).' '.html_print_image('images/arrow_down_green.png', true, ['class' => 'module_graph_menu_arrow', 'float' => 'left'], false, false, true).'
<span>'.__('Graph configuration menu').ui_print_help_icon('graphs', true, $config['homeurl'], 'images/help_g.png', true).'</span> <span>'.__('Graph configuration menu').'</span>
'.html_print_image('images/config.png', true, ['float' => 'right'], false, false, true).' '.html_print_image('images/config.png', true, ['float' => 'right'], false, false, true).'
</div> </div>
<div class="module_graph_menu_content module_graph_menu_content_closed" style="display:none;">'.$form_table.'</div> <div class="module_graph_menu_content module_graph_menu_content_closed" style="display:none;">'.$form_table.'</div>

View File

@ -1389,6 +1389,34 @@ if (!empty($result)) {
true true
); );
} }
} else if ($row['estado'] == 3) {
if (is_numeric($row['datos'])) {
$data[6] = ui_print_status_image(
STATUS_MODULE_UNKNOWN,
__('UNKNOWN').': '.remove_right_zeros(number_format($row['datos'], $config['graph_precision'])),
true
);
} else {
$data[6] = ui_print_status_image(
STATUS_MODULE_UNKNOWN,
__('UNKNOWN').': '.$row['datos'],
true
);
}
} else if ($row['estado'] == 4) {
if (is_numeric($row['datos'])) {
$data[6] = ui_print_status_image(
STATUS_MODULE_NO_DATA,
__('NO DATA').': '.remove_right_zeros(number_format($row['datos'], $config['graph_precision'])),
true
);
} else {
$data[6] = ui_print_status_image(
STATUS_MODULE_NO_DATA,
__('NO DATA').': '.$row['datos'],
true
);
}
} else { } else {
$last_status = modules_get_agentmodule_last_status( $last_status = modules_get_agentmodule_last_status(
$row['id_agente_modulo'] $row['id_agente_modulo']

View File

@ -66,7 +66,7 @@ if (check_acl($config['id_user'], 0, 'AR')) {
enterprise_hook('inventory_menu'); enterprise_hook('inventory_menu');
if ($config['activate_netflow'] || $config['activate_nta']) { if ($config['activate_netflow'] || $config['activate_nta']) {
$sub['network'] = [ $sub['network_traffic'] = [
'text' => __('Network'), 'text' => __('Network'),
'id' => 'Network', 'id' => 'Network',
'type' => 'direct', 'type' => 'direct',
@ -117,7 +117,7 @@ if (check_acl($config['id_user'], 0, 'AR')) {
); );
} }
$sub['network']['sub2'] = $netflow_sub; $sub['network_traffic']['sub2'] = $netflow_sub;
} }
if ($config['log_collector'] == 1) { if ($config['log_collector'] == 1) {

View File

@ -198,6 +198,14 @@ $visualConsoleItems = VisualConsole::getItemsFromDB(
} }
} }
} }
// Add the datetime when the item was received.
var receivedAt = new Date();
items.map(function(item) {
item["receivedAt"] = receivedAt;
return item;
});
var visualConsoleManager = createVisualConsole( var visualConsoleManager = createVisualConsole(
container, container,
props, props,

View File

@ -155,6 +155,16 @@ if (!is_metaconsole()) {
html_print_input_hidden('metaconsole', 1); html_print_input_hidden('metaconsole', 1);
} }
if ($pure === false) {
echo '<div class="visual-console-edit-controls">';
echo '<span>'.__('Move and resize mode').'</span>';
echo '<span>';
echo html_print_checkbox_switch('edit-mode', 1, false, true);
echo '</span>';
echo '</div>';
echo '<br />';
}
echo '<div id="visual-console-container"></div>'; echo '<div id="visual-console-container"></div>';
if ($pure === true) { if ($pure === true) {
@ -306,6 +316,14 @@ $visualConsoleItems = VisualConsole::getItemsFromDB(
} }
} }
} }
// Add the datetime when the item was received.
var receivedAt = new Date();
items.map(function(item) {
item["receivedAt"] = receivedAt;
return item;
});
var visualConsoleManager = createVisualConsole( var visualConsoleManager = createVisualConsole(
container, container,
props, props,
@ -315,6 +333,17 @@ $visualConsoleItems = VisualConsole::getItemsFromDB(
handleUpdate handleUpdate
); );
// Enable/disable the edition mode.
$('input[name=edit-mode]').change(function(event) {
if ($(this).prop('checked')) {
visualConsoleManager.visualConsole.enableEditMode();
visualConsoleManager.changeUpdateInterval(0);
} else {
visualConsoleManager.visualConsole.disableEditMode();
visualConsoleManager.changeUpdateInterval(<?php echo ($refr * 1000); ?>); // To ms.
}
});
// Update the data fetch interval. // Update the data fetch interval.
$('select#vc-refr').change(function(event) { $('select#vc-refr').change(function(event) {
var refr = Number.parseInt(event.target.value); var refr = Number.parseInt(event.target.value);

View File

@ -3,7 +3,7 @@
# #
%define name pandorafms_console %define name pandorafms_console
%define version 7.0NG.735 %define version 7.0NG.735
%define release 190610 %define release 190617
# User and Group under which Apache is running # User and Group under which Apache is running
%define httpd_name httpd %define httpd_name httpd

View File

@ -3,7 +3,7 @@
# #
%define name pandorafms_console %define name pandorafms_console
%define version 7.0NG.735 %define version 7.0NG.735
%define release 190610 %define release 190617
# User and Group under which Apache is running # User and Group under which Apache is running
%define httpd_name httpd %define httpd_name httpd

View File

@ -3,7 +3,7 @@
# #
%define name pandorafms_console %define name pandorafms_console
%define version 7.0NG.735 %define version 7.0NG.735
%define release 190610 %define release 190617
%define httpd_name httpd %define httpd_name httpd
# User and Group under which Apache is running # User and Group under which Apache is running
%define httpd_name apache2 %define httpd_name apache2

View File

@ -1,5 +1,5 @@
package: pandorafms-server package: pandorafms-server
Version: 7.0NG.735-190610 Version: 7.0NG.735-190617
Architecture: all Architecture: all
Priority: optional Priority: optional
Section: admin Section: admin

View File

@ -14,7 +14,7 @@
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
pandora_version="7.0NG.735-190610" pandora_version="7.0NG.735-190617"
package_cpan=0 package_cpan=0
package_pandora=1 package_pandora=1

View File

@ -45,7 +45,7 @@ our @EXPORT = qw(
# version: Defines actual version of Pandora Server for this module only # version: Defines actual version of Pandora Server for this module only
my $pandora_version = "7.0NG.735"; my $pandora_version = "7.0NG.735";
my $pandora_build = "190610"; my $pandora_build = "190617";
our $VERSION = $pandora_version." ".$pandora_build; our $VERSION = $pandora_version." ".$pandora_build;
# Setup hash # Setup hash

View File

@ -3352,7 +3352,7 @@ sub pandora_event ($$$$$$$$$$;$$$$$$$$$$$) {
# Validate events with the same event id # Validate events with the same event id
if (defined ($id_extra) && $id_extra ne '') { if (defined ($id_extra) && $id_extra ne '') {
logger($pa_config, "Updating events with extended id '$id_extra'.", 10); logger($pa_config, "Updating events with extended id '$id_extra'.", 10);
db_do ($dbh, 'UPDATE ' . $event_table . ' SET estado = 1, ack_utimestamp = ? WHERE estado = 0 AND id_extra=?', $utimestamp, $id_extra); db_do ($dbh, 'UPDATE ' . $event_table . ' SET estado = 1, ack_utimestamp = ? WHERE estado IN (0,2) AND id_extra=?', $utimestamp, $id_extra);
} }
# Create the event # Create the event

View File

@ -32,7 +32,7 @@ our @ISA = qw(Exporter);
# version: Defines actual version of Pandora Server for this module only # version: Defines actual version of Pandora Server for this module only
my $pandora_version = "7.0NG.735"; my $pandora_version = "7.0NG.735";
my $pandora_build = "190610"; my $pandora_build = "190617";
our $VERSION = $pandora_version." ".$pandora_build; our $VERSION = $pandora_version." ".$pandora_build;
our %EXPORT_TAGS = ( 'all' => [ qw() ] ); our %EXPORT_TAGS = ( 'all' => [ qw() ] );

View File

@ -3,7 +3,7 @@
# #
%define name pandorafms_server %define name pandorafms_server
%define version 7.0NG.735 %define version 7.0NG.735
%define release 190610 %define release 190617
Summary: Pandora FMS Server Summary: Pandora FMS Server
Name: %{name} Name: %{name}

View File

@ -3,7 +3,7 @@
# #
%define name pandorafms_server %define name pandorafms_server
%define version 7.0NG.735 %define version 7.0NG.735
%define release 190610 %define release 190617
Summary: Pandora FMS Server Summary: Pandora FMS Server
Name: %{name} Name: %{name}

View File

@ -9,7 +9,7 @@
# ********************************************************************** # **********************************************************************
PI_VERSION="7.0NG.735" PI_VERSION="7.0NG.735"
PI_BUILD="190610" PI_BUILD="190617"
MODE=$1 MODE=$1
if [ $# -gt 1 ]; then if [ $# -gt 1 ]; then

View File

@ -34,7 +34,7 @@ use PandoraFMS::Config;
use PandoraFMS::DB; use PandoraFMS::DB;
# version: define current version # version: define current version
my $version = "7.0NG.735 PS190610"; my $version = "7.0NG.735 PS190617";
# Pandora server configuration # Pandora server configuration
my %conf; my %conf;

View File

@ -36,7 +36,7 @@ use Encode::Locale;
Encode::Locale::decode_argv; Encode::Locale::decode_argv;
# version: define current version # version: define current version
my $version = "7.0NG.735 PS190610"; my $version = "7.0NG.735 PS190617";
# save program name for logging # save program name for logging
my $progname = basename($0); my $progname = basename($0);

View File

@ -68,27 +68,16 @@ then
help help
fi fi
TMPFILE=/tmp/dns_$DNS_CHECK.tmp
dig @$DNS_CHECK $DOMAIN_CHECK > $TMPFILE results=`dig @$DNS_CHECK +nocmd $DOMAIN_CHECK +multiline +noall +answer A`
RETURN_IP=`cat $TMPFILE | grep "^$DOMAIN_CHECK" | awk '{print $5}'` targets=`echo "$results"| awk '{print $5}'`
RETURN_TIMEOUT=`cat $TMPFILE | grep "Query time" | grep -o "[0-9]*"`
rm $TMPFILE 2> /dev/null
if [ $TIMEOUT_CHECK == 1 ]
then
echo $RETURN_TIMEOUT
exit 0
fi
if [ "$RETURN_IP" != "$IP_CHECK" ]
then
echo 0
exit 1
else
echo 1
exit 0
fi
for x in $targets; do
if [ "$x" == "$IP_CHECK" ]; then
echo 1
exit 0
fi
done
echo 0
exit 0

View File

@ -1,4 +1,10 @@
import { Position, Size, UnknownObject, WithModuleProps } from "./types"; import {
Position,
Size,
AnyObject,
WithModuleProps,
ItemMeta
} from "./lib/types";
import { import {
sizePropsDecoder, sizePropsDecoder,
positionPropsDecoder, positionPropsDecoder,
@ -9,7 +15,7 @@ import {
humanDate, humanDate,
humanTime humanTime
} from "./lib"; } from "./lib";
import TypedEvent, { Listener, Disposable } from "./TypedEvent"; import TypedEvent, { Listener, Disposable } from "./lib/TypedEvent";
// Enum: https://www.typescriptlang.org/docs/handbook/enums.html. // Enum: https://www.typescriptlang.org/docs/handbook/enums.html.
export const enum ItemType { export const enum ItemType {
@ -52,14 +58,14 @@ export interface ItemProps extends Position, Size {
// FIXME: Fix type compatibility. // FIXME: Fix type compatibility.
export interface ItemClickEvent<Props extends ItemProps> { export interface ItemClickEvent<Props extends ItemProps> {
// data: Props; // data: Props;
data: UnknownObject; data: AnyObject;
nativeEvent: Event; nativeEvent: Event;
} }
// FIXME: Fix type compatibility. // FIXME: Fix type compatibility.
export interface ItemRemoveEvent<Props extends ItemProps> { export interface ItemRemoveEvent<Props extends ItemProps> {
// data: Props; // data: Props;
data: UnknownObject; data: AnyObject;
} }
/** /**
@ -89,7 +95,7 @@ const parseLabelPosition = (
* @throws Will throw a TypeError if some property * @throws Will throw a TypeError if some property
* is missing from the raw object or have an invalid type. * is missing from the raw object or have an invalid type.
*/ */
export function itemBasePropsDecoder(data: UnknownObject): ItemProps | never { export function itemBasePropsDecoder(data: AnyObject): ItemProps | never {
if (data.id == null || isNaN(parseInt(data.id))) { if (data.id == null || isNaN(parseInt(data.id))) {
throw new TypeError("invalid id."); throw new TypeError("invalid id.");
} }
@ -118,6 +124,8 @@ export function itemBasePropsDecoder(data: UnknownObject): ItemProps | never {
abstract class VisualConsoleItem<Props extends ItemProps> { abstract class VisualConsoleItem<Props extends ItemProps> {
// Properties of the item. // Properties of the item.
private itemProps: Props; private itemProps: Props;
// Metadata of the item.
private _metadata: ItemMeta;
// Reference to the DOM element which will contain the item. // Reference to the DOM element which will contain the item.
public elementRef: HTMLElement; public elementRef: HTMLElement;
public readonly labelElementRef: HTMLElement; public readonly labelElementRef: HTMLElement;
@ -138,8 +146,9 @@ abstract class VisualConsoleItem<Props extends ItemProps> {
*/ */
protected abstract createDomElement(): HTMLElement; protected abstract createDomElement(): HTMLElement;
public constructor(props: Props) { public constructor(props: Props, metadata: ItemMeta) {
this.itemProps = props; this.itemProps = props;
this._metadata = metadata;
/* /*
* Get a HTMLElement which represents the container box * Get a HTMLElement which represents the container box
@ -185,8 +194,14 @@ abstract class VisualConsoleItem<Props extends ItemProps> {
box.style.zIndex = this.props.isOnTop ? "2" : "1"; box.style.zIndex = this.props.isOnTop ? "2" : "1";
box.style.left = `${this.props.x}px`; box.style.left = `${this.props.x}px`;
box.style.top = `${this.props.y}px`; box.style.top = `${this.props.y}px`;
box.onclick = e => box.addEventListener("click", e => {
this.clickEventManager.emit({ data: this.props, nativeEvent: e }); if (this.meta.editMode) {
e.preventDefault();
e.stopPropagation();
} else {
this.clickEventManager.emit({ data: this.props, nativeEvent: e });
}
});
return box; return box;
} }
@ -310,7 +325,34 @@ abstract class VisualConsoleItem<Props extends ItemProps> {
// From this point, things which rely on this.props can access to the changes. // From this point, things which rely on this.props can access to the changes.
// Check if we should re-render. // Check if we should re-render.
if (this.shouldBeUpdated(prevProps, newProps)) this.render(prevProps); if (this.shouldBeUpdated(prevProps, newProps))
this.render(prevProps, this._metadata);
}
/**
* Public accessor of the `meta` property.
* @return Properties.
*/
public get meta(): ItemMeta {
return { ...this._metadata }; // Return a copy.
}
/**
* Public setter of the `meta` property.
* If the new meta are different enough than the
* stored meta, a render would be fired.
* @param newProps
*/
public set meta(newMetadata: ItemMeta) {
const prevMetadata = this._metadata;
// Update the internal meta.
this._metadata = newMetadata;
// From this point, things which rely on this.props can access to the changes.
// Check if we should re-render.
// if (this.shouldBeUpdated(prevMetadata, newMetadata))
this.render(this.itemProps, prevMetadata);
} }
/** /**
@ -333,7 +375,10 @@ abstract class VisualConsoleItem<Props extends ItemProps> {
* To recreate or update the HTMLElement which represents the item into the DOM. * To recreate or update the HTMLElement which represents the item into the DOM.
* @param prevProps If exists it will be used to only perform DOM updates instead of a full replace. * @param prevProps If exists it will be used to only perform DOM updates instead of a full replace.
*/ */
public render(prevProps: Props | null = null): void { public render(
prevProps: Props | null = null,
prevMeta: ItemMeta | null = null
): void {
this.updateDomElement(this.childElementRef); this.updateDomElement(this.childElementRef);
// Move box. // Move box.
@ -378,6 +423,29 @@ abstract class VisualConsoleItem<Props extends ItemProps> {
// Changed the reference to the main element. It's ugly, but needed. // Changed the reference to the main element. It's ugly, but needed.
this.elementRef = container; this.elementRef = container;
} }
// Change metadata related things.
if (!prevMeta || prevMeta.editMode !== this.meta.editMode) {
if (this.meta.editMode) {
this.elementRef.classList.add("is-editing");
} else {
this.elementRef.classList.remove("is-editing");
}
}
if (!prevMeta || prevMeta.isFetching !== this.meta.isFetching) {
if (this.meta.isFetching) {
this.elementRef.classList.add("is-fetching");
} else {
this.elementRef.classList.remove("is-fetching");
}
}
if (!prevMeta || prevMeta.isUpdating !== this.meta.isUpdating) {
if (this.meta.isUpdating) {
this.elementRef.classList.add("is-updating");
} else {
this.elementRef.classList.remove("is-updating");
}
}
} }
/** /**

View File

@ -1,9 +1,10 @@
import { UnknownObject, Size } from "./types"; import { AnyObject, Size } from "./lib/types";
import { import {
parseBoolean, parseBoolean,
sizePropsDecoder, sizePropsDecoder,
parseIntOr, parseIntOr,
notEmptyStringOr notEmptyStringOr,
itemMetaDecoder
} from "./lib"; } from "./lib";
import Item, { import Item, {
ItemType, ItemType,
@ -24,7 +25,7 @@ import EventsHistory, {
eventsHistoryPropsDecoder eventsHistoryPropsDecoder
} from "./items/EventsHistory"; } from "./items/EventsHistory";
import Percentile, { percentilePropsDecoder } from "./items/Percentile"; import Percentile, { percentilePropsDecoder } from "./items/Percentile";
import TypedEvent, { Disposable, Listener } from "./TypedEvent"; import TypedEvent, { Disposable, Listener } from "./lib/TypedEvent";
import DonutGraph, { donutGraphPropsDecoder } from "./items/DonutGraph"; import DonutGraph, { donutGraphPropsDecoder } from "./items/DonutGraph";
import BarsGraph, { barsGraphPropsDecoder } from "./items/BarsGraph"; import BarsGraph, { barsGraphPropsDecoder } from "./items/BarsGraph";
import ModuleGraph, { moduleGraphPropsDecoder } from "./items/ModuleGraph"; import ModuleGraph, { moduleGraphPropsDecoder } from "./items/ModuleGraph";
@ -32,47 +33,49 @@ import Service, { servicePropsDecoder } from "./items/Service";
// TODO: Document. // TODO: Document.
// eslint-disable-next-line @typescript-eslint/explicit-function-return-type // eslint-disable-next-line @typescript-eslint/explicit-function-return-type
function itemInstanceFrom(data: UnknownObject) { function itemInstanceFrom(data: AnyObject) {
const type = parseIntOr(data.type, null); const type = parseIntOr(data.type, null);
if (type == null) throw new TypeError("missing item type."); if (type == null) throw new TypeError("missing item type.");
const meta = itemMetaDecoder(data);
switch (type as ItemType) { switch (type as ItemType) {
case ItemType.STATIC_GRAPH: case ItemType.STATIC_GRAPH:
return new StaticGraph(staticGraphPropsDecoder(data)); return new StaticGraph(staticGraphPropsDecoder(data), meta);
case ItemType.MODULE_GRAPH: case ItemType.MODULE_GRAPH:
return new ModuleGraph(moduleGraphPropsDecoder(data)); return new ModuleGraph(moduleGraphPropsDecoder(data), meta);
case ItemType.SIMPLE_VALUE: case ItemType.SIMPLE_VALUE:
case ItemType.SIMPLE_VALUE_MAX: case ItemType.SIMPLE_VALUE_MAX:
case ItemType.SIMPLE_VALUE_MIN: case ItemType.SIMPLE_VALUE_MIN:
case ItemType.SIMPLE_VALUE_AVG: case ItemType.SIMPLE_VALUE_AVG:
return new SimpleValue(simpleValuePropsDecoder(data)); return new SimpleValue(simpleValuePropsDecoder(data), meta);
case ItemType.PERCENTILE_BAR: case ItemType.PERCENTILE_BAR:
case ItemType.PERCENTILE_BUBBLE: case ItemType.PERCENTILE_BUBBLE:
case ItemType.CIRCULAR_PROGRESS_BAR: case ItemType.CIRCULAR_PROGRESS_BAR:
case ItemType.CIRCULAR_INTERIOR_PROGRESS_BAR: case ItemType.CIRCULAR_INTERIOR_PROGRESS_BAR:
return new Percentile(percentilePropsDecoder(data)); return new Percentile(percentilePropsDecoder(data), meta);
case ItemType.LABEL: case ItemType.LABEL:
return new Label(labelPropsDecoder(data)); return new Label(labelPropsDecoder(data), meta);
case ItemType.ICON: case ItemType.ICON:
return new Icon(iconPropsDecoder(data)); return new Icon(iconPropsDecoder(data), meta);
case ItemType.SERVICE: case ItemType.SERVICE:
return new Service(servicePropsDecoder(data)); return new Service(servicePropsDecoder(data), meta);
case ItemType.GROUP_ITEM: case ItemType.GROUP_ITEM:
return new Group(groupPropsDecoder(data)); return new Group(groupPropsDecoder(data), meta);
case ItemType.BOX_ITEM: case ItemType.BOX_ITEM:
return new Box(boxPropsDecoder(data)); return new Box(boxPropsDecoder(data), meta);
case ItemType.LINE_ITEM: case ItemType.LINE_ITEM:
return new Line(linePropsDecoder(data)); return new Line(linePropsDecoder(data), meta);
case ItemType.AUTO_SLA_GRAPH: case ItemType.AUTO_SLA_GRAPH:
return new EventsHistory(eventsHistoryPropsDecoder(data)); return new EventsHistory(eventsHistoryPropsDecoder(data), meta);
case ItemType.DONUT_GRAPH: case ItemType.DONUT_GRAPH:
return new DonutGraph(donutGraphPropsDecoder(data)); return new DonutGraph(donutGraphPropsDecoder(data), meta);
case ItemType.BARS_GRAPH: case ItemType.BARS_GRAPH:
return new BarsGraph(barsGraphPropsDecoder(data)); return new BarsGraph(barsGraphPropsDecoder(data), meta);
case ItemType.CLOCK: case ItemType.CLOCK:
return new Clock(clockPropsDecoder(data)); return new Clock(clockPropsDecoder(data), meta);
case ItemType.COLOR_CLOUD: case ItemType.COLOR_CLOUD:
return new ColorCloud(colorCloudPropsDecoder(data)); return new ColorCloud(colorCloudPropsDecoder(data), meta);
default: default:
throw new TypeError("item not found"); throw new TypeError("item not found");
} }
@ -80,7 +83,7 @@ function itemInstanceFrom(data: UnknownObject) {
// TODO: Document. // TODO: Document.
// eslint-disable-next-line @typescript-eslint/explicit-function-return-type // eslint-disable-next-line @typescript-eslint/explicit-function-return-type
function decodeProps(data: UnknownObject) { function decodeProps(data: AnyObject) {
const type = parseIntOr(data.type, null); const type = parseIntOr(data.type, null);
if (type == null) throw new TypeError("missing item type."); if (type == null) throw new TypeError("missing item type.");
@ -147,7 +150,7 @@ export interface VisualConsoleProps extends Size {
* is missing from the raw object or have an invalid type. * is missing from the raw object or have an invalid type.
*/ */
export function visualConsolePropsDecoder( export function visualConsolePropsDecoder(
data: UnknownObject data: AnyObject
): VisualConsoleProps | never { ): VisualConsoleProps | never {
// Object destructuring: http://es6-features.org/#ObjectMatchingShorthandNotation // Object destructuring: http://es6-features.org/#ObjectMatchingShorthandNotation
const { const {
@ -226,8 +229,8 @@ export default class VisualConsole {
public constructor( public constructor(
container: HTMLElement, container: HTMLElement,
props: UnknownObject, props: AnyObject,
items: UnknownObject[] items: AnyObject[]
) { ) {
this.containerRef = container; this.containerRef = container;
this._props = visualConsolePropsDecoder(props); this._props = visualConsolePropsDecoder(props);
@ -288,13 +291,13 @@ export default class VisualConsole {
* Public setter of the `elements` property. * Public setter of the `elements` property.
* @param items. * @param items.
*/ */
public updateElements(items: UnknownObject[]): void { public updateElements(items: AnyObject[]): void {
const itemIds = items.map(item => item.id || null).filter(id => id != null); // Ensure the type cause Typescript doesn't know the filter removes null items.
itemIds as number[]; // Tell the type system to rely on us. const itemIds = items
.map(item => item.id || null)
.filter(id => id != null) as number[];
// Get the elements we should delete. // Get the elements we should delete.
const deletedIds: number[] = this.elementIds.filter( const deletedIds = this.elementIds.filter(id => itemIds.indexOf(id) < 0);
id => itemIds.indexOf(id) < 0
);
// Delete the elements. // Delete the elements.
deletedIds.forEach(id => { deletedIds.forEach(id => {
if (this.elementsById[id] != null) { if (this.elementsById[id] != null) {
@ -530,6 +533,9 @@ export default class VisualConsole {
height: 0, height: 0,
lineWidth: this.props.relationLineWidth, lineWidth: this.props.relationLineWidth,
color: "#CCCCCC" color: "#CCCCCC"
}),
itemMetaDecoder({
receivedAt: new Date()
}) })
); );
// Save a reference to the line item. // Save a reference to the line item.
@ -557,4 +563,22 @@ export default class VisualConsole {
return disposable; return disposable;
} }
/**
* Enable the edition mode.
*/
public enableEditMode(): void {
this.elements.forEach(item => {
item.meta = { ...item.meta, editMode: true };
});
}
/**
* Disable the edition mode.
*/
public disableEditMode(): void {
this.elements.forEach(item => {
item.meta = { ...item.meta, editMode: false };
});
}
} }

View File

@ -1,4 +1,4 @@
import { UnknownObject, WithModuleProps } from "../types"; import { AnyObject, WithModuleProps } from "../lib/types";
import { modulePropsDecoder, decodeBase64, stringIsEmpty } from "../lib"; import { modulePropsDecoder, decodeBase64, stringIsEmpty } from "../lib";
import Item, { ItemType, ItemProps, itemBasePropsDecoder } from "../Item"; import Item, { ItemType, ItemProps, itemBasePropsDecoder } from "../Item";
@ -17,9 +17,7 @@ export type BarsGraphProps = {
* @throws Will throw a TypeError if some property * @throws Will throw a TypeError if some property
* is missing from the raw object or have an invalid type. * is missing from the raw object or have an invalid type.
*/ */
export function barsGraphPropsDecoder( export function barsGraphPropsDecoder(data: AnyObject): BarsGraphProps | never {
data: UnknownObject
): BarsGraphProps | never {
if (stringIsEmpty(data.html) && stringIsEmpty(data.encodedHtml)) { if (stringIsEmpty(data.html) && stringIsEmpty(data.encodedHtml)) {
throw new TypeError("missing html content."); throw new TypeError("missing html content.");
} }

View File

@ -1,4 +1,4 @@
import { UnknownObject } from "../types"; import { AnyObject } from "../lib/types";
import { parseIntOr, notEmptyStringOr } from "../lib"; import { parseIntOr, notEmptyStringOr } from "../lib";
import Item, { ItemType, ItemProps, itemBasePropsDecoder } from "../Item"; import Item, { ItemType, ItemProps, itemBasePropsDecoder } from "../Item";
@ -24,7 +24,7 @@ interface BoxProps extends ItemProps {
* @throws Will throw a TypeError if some property * @throws Will throw a TypeError if some property
* is missing from the raw object or have an invalid type. * is missing from the raw object or have an invalid type.
*/ */
export function boxPropsDecoder(data: UnknownObject): BoxProps | never { export function boxPropsDecoder(data: AnyObject): BoxProps | never {
return { return {
...itemBasePropsDecoder(data), // Object spread. It will merge the properties of the two objects. ...itemBasePropsDecoder(data), // Object spread. It will merge the properties of the two objects.
type: ItemType.BOX_ITEM, type: ItemType.BOX_ITEM,

View File

@ -1,6 +1,11 @@
import "./styles.css"; import "./styles.css";
import { LinkedVisualConsoleProps, UnknownObject, Size } from "../../types"; import {
LinkedVisualConsoleProps,
AnyObject,
Size,
ItemMeta
} from "../../lib/types";
import { import {
linkedVCPropsDecoder, linkedVCPropsDecoder,
parseIntOr, parseIntOr,
@ -60,7 +65,7 @@ const parseClockFormat = (clockFormat: unknown): ClockProps["clockFormat"] => {
* @throws Will throw a TypeError if some property * @throws Will throw a TypeError if some property
* is missing from the raw object or have an invalid type. * is missing from the raw object or have an invalid type.
*/ */
export function clockPropsDecoder(data: UnknownObject): ClockProps | never { export function clockPropsDecoder(data: AnyObject): ClockProps | never {
if ( if (
typeof data.clockTimezone !== "string" || typeof data.clockTimezone !== "string" ||
data.clockTimezone.length === 0 data.clockTimezone.length === 0
@ -85,9 +90,9 @@ export default class Clock extends Item<ClockProps> {
public static readonly TICK_INTERVAL = 1000; // In ms. public static readonly TICK_INTERVAL = 1000; // In ms.
private intervalRef: number | null = null; private intervalRef: number | null = null;
public constructor(props: ClockProps) { public constructor(props: ClockProps, meta: ItemMeta) {
// Call the superclass constructor. // Call the superclass constructor.
super(props); super(props, meta);
/* The item is already loaded and inserted into the DOM. /* The item is already loaded and inserted into the DOM.
* The class properties are now initialized. * The class properties are now initialized.

View File

@ -1,4 +1,5 @@
import Clock, { clockPropsDecoder } from "."; import Clock, { clockPropsDecoder } from ".";
import { itemMetaDecoder } from "../../lib";
const genericRawProps = { const genericRawProps = {
id: 1, id: 1,
@ -46,6 +47,9 @@ describe("Clock item", () => {
...sizeRawProps, ...sizeRawProps,
...linkedModuleProps, ...linkedModuleProps,
...digitalClockProps ...digitalClockProps
}),
itemMetaDecoder({
receivedAt: new Date(1)
}) })
); );

View File

@ -1,4 +1,5 @@
import ColorCloud, { colorCloudPropsDecoder } from "./ColorCloud"; import ColorCloud, { colorCloudPropsDecoder } from "./ColorCloud";
import { itemMetaDecoder } from "../lib";
const genericRawProps = { const genericRawProps = {
id: 1, id: 1,
@ -41,6 +42,9 @@ describe("Color cloud item", () => {
...sizeRawProps, ...sizeRawProps,
...linkedModuleProps, ...linkedModuleProps,
...colorCloudProps ...colorCloudProps
}),
itemMetaDecoder({
receivedAt: new Date(1)
}) })
); );

View File

@ -1,8 +1,8 @@
import { import {
WithModuleProps, WithModuleProps,
LinkedVisualConsoleProps, LinkedVisualConsoleProps,
UnknownObject AnyObject
} from "../types"; } from "../lib/types";
import { modulePropsDecoder, linkedVCPropsDecoder } from "../lib"; import { modulePropsDecoder, linkedVCPropsDecoder } from "../lib";
import Item, { itemBasePropsDecoder, ItemType, ItemProps } from "../Item"; import Item, { itemBasePropsDecoder, ItemType, ItemProps } from "../Item";
@ -24,7 +24,7 @@ export type ColorCloudProps = {
* is missing from the raw object or have an invalid type. * is missing from the raw object or have an invalid type.
*/ */
export function colorCloudPropsDecoder( export function colorCloudPropsDecoder(
data: UnknownObject data: AnyObject
): ColorCloudProps | never { ): ColorCloudProps | never {
// TODO: Validate the color. // TODO: Validate the color.
if (typeof data.color !== "string" || data.color.length === 0) { if (typeof data.color !== "string" || data.color.length === 0) {

View File

@ -1,8 +1,8 @@
import { import {
LinkedVisualConsoleProps, LinkedVisualConsoleProps,
UnknownObject, AnyObject,
WithModuleProps WithModuleProps
} from "../types"; } from "../lib/types";
import { import {
linkedVCPropsDecoder, linkedVCPropsDecoder,
modulePropsDecoder, modulePropsDecoder,
@ -28,7 +28,7 @@ export type DonutGraphProps = {
* is missing from the raw object or have an invalid type. * is missing from the raw object or have an invalid type.
*/ */
export function donutGraphPropsDecoder( export function donutGraphPropsDecoder(
data: UnknownObject data: AnyObject
): DonutGraphProps | never { ): DonutGraphProps | never {
if (stringIsEmpty(data.html) && stringIsEmpty(data.encodedHtml)) { if (stringIsEmpty(data.html) && stringIsEmpty(data.encodedHtml)) {
throw new TypeError("missing html content."); throw new TypeError("missing html content.");

View File

@ -1,4 +1,4 @@
import { UnknownObject, WithModuleProps } from "../types"; import { AnyObject, WithModuleProps } from "../lib/types";
import { import {
modulePropsDecoder, modulePropsDecoder,
parseIntOr, parseIntOr,
@ -24,7 +24,7 @@ export type EventsHistoryProps = {
* is missing from the raw object or have an invalid type. * is missing from the raw object or have an invalid type.
*/ */
export function eventsHistoryPropsDecoder( export function eventsHistoryPropsDecoder(
data: UnknownObject data: AnyObject
): EventsHistoryProps | never { ): EventsHistoryProps | never {
if (stringIsEmpty(data.html) && stringIsEmpty(data.encodedHtml)) { if (stringIsEmpty(data.html) && stringIsEmpty(data.encodedHtml)) {
throw new TypeError("missing html content."); throw new TypeError("missing html content.");

View File

@ -1,4 +1,5 @@
import Group, { groupPropsDecoder } from "./Group"; import Group, { groupPropsDecoder } from "./Group";
import { itemMetaDecoder } from "../lib";
const genericRawProps = { const genericRawProps = {
id: 1, id: 1,
@ -33,6 +34,9 @@ describe("Group item", () => {
...positionRawProps, ...positionRawProps,
...sizeRawProps, ...sizeRawProps,
...groupRawProps ...groupRawProps
}),
itemMetaDecoder({
receivedAt: new Date(1)
}) })
); );

View File

@ -1,4 +1,4 @@
import { LinkedVisualConsoleProps, UnknownObject } from "../types"; import { LinkedVisualConsoleProps, AnyObject } from "../lib/types";
import { import {
linkedVCPropsDecoder, linkedVCPropsDecoder,
parseIntOr, parseIntOr,
@ -19,7 +19,7 @@ export type GroupProps = {
} & ItemProps & } & ItemProps &
LinkedVisualConsoleProps; LinkedVisualConsoleProps;
function extractHtml(data: UnknownObject): string | null { function extractHtml(data: AnyObject): string | null {
if (!stringIsEmpty(data.html)) return data.html; if (!stringIsEmpty(data.html)) return data.html;
if (!stringIsEmpty(data.encodedHtml)) return decodeBase64(data.encodedHtml); if (!stringIsEmpty(data.encodedHtml)) return decodeBase64(data.encodedHtml);
return null; return null;
@ -34,7 +34,7 @@ function extractHtml(data: UnknownObject): string | null {
* @throws Will throw a TypeError if some property * @throws Will throw a TypeError if some property
* is missing from the raw object or have an invalid type. * is missing from the raw object or have an invalid type.
*/ */
export function groupPropsDecoder(data: UnknownObject): GroupProps | never { export function groupPropsDecoder(data: AnyObject): GroupProps | never {
if ( if (
(typeof data.imageSrc !== "string" || data.imageSrc.length === 0) && (typeof data.imageSrc !== "string" || data.imageSrc.length === 0) &&
data.encodedHtml === null data.encodedHtml === null

View File

@ -1,4 +1,4 @@
import { LinkedVisualConsoleProps, UnknownObject } from "../types"; import { LinkedVisualConsoleProps, AnyObject } from "../lib/types";
import { linkedVCPropsDecoder } from "../lib"; import { linkedVCPropsDecoder } from "../lib";
import Item, { ItemType, ItemProps, itemBasePropsDecoder } from "../Item"; import Item, { ItemType, ItemProps, itemBasePropsDecoder } from "../Item";
@ -17,7 +17,7 @@ export type IconProps = {
* @throws Will throw a TypeError if some property * @throws Will throw a TypeError if some property
* is missing from the raw object or have an invalid type. * is missing from the raw object or have an invalid type.
*/ */
export function iconPropsDecoder(data: UnknownObject): IconProps | never { export function iconPropsDecoder(data: AnyObject): IconProps | never {
if (typeof data.imageSrc !== "string" || data.imageSrc.length === 0) { if (typeof data.imageSrc !== "string" || data.imageSrc.length === 0) {
throw new TypeError("invalid image src."); throw new TypeError("invalid image src.");
} }

View File

@ -1,4 +1,4 @@
import { LinkedVisualConsoleProps, UnknownObject } from "../types"; import { LinkedVisualConsoleProps, AnyObject } from "../lib/types";
import { linkedVCPropsDecoder } from "../lib"; import { linkedVCPropsDecoder } from "../lib";
import Item, { ItemType, ItemProps, itemBasePropsDecoder } from "../Item"; import Item, { ItemType, ItemProps, itemBasePropsDecoder } from "../Item";
@ -16,7 +16,7 @@ export type LabelProps = {
* @throws Will throw a TypeError if some property * @throws Will throw a TypeError if some property
* is missing from the raw object or have an invalid type. * is missing from the raw object or have an invalid type.
*/ */
export function labelPropsDecoder(data: UnknownObject): LabelProps | never { export function labelPropsDecoder(data: AnyObject): LabelProps | never {
return { return {
...itemBasePropsDecoder(data), // Object spread. It will merge the properties of the two objects. ...itemBasePropsDecoder(data), // Object spread. It will merge the properties of the two objects.
type: ItemType.LABEL, type: ItemType.LABEL,

View File

@ -1,4 +1,4 @@
import { UnknownObject, Position, Size } from "../types"; import { AnyObject, Position, Size, ItemMeta } from "../lib/types";
import { parseIntOr, notEmptyStringOr } from "../lib"; import { parseIntOr, notEmptyStringOr } from "../lib";
import Item, { ItemType, ItemProps, itemBasePropsDecoder } from "../Item"; import Item, { ItemType, ItemProps, itemBasePropsDecoder } from "../Item";
@ -25,7 +25,7 @@ interface LineProps extends ItemProps {
* @throws Will throw a TypeError if some property * @throws Will throw a TypeError if some property
* is missing from the raw object or have an invalid type. * is missing from the raw object or have an invalid type.
*/ */
export function linePropsDecoder(data: UnknownObject): LineProps | never { export function linePropsDecoder(data: AnyObject): LineProps | never {
const props: LineProps = { const props: LineProps = {
...itemBasePropsDecoder({ ...data, width: 1, height: 1 }), // Object spread. It will merge the properties of the two objects. ...itemBasePropsDecoder({ ...data, width: 1, height: 1 }), // Object spread. It will merge the properties of the two objects.
type: ItemType.LINE_ITEM, type: ItemType.LINE_ITEM,
@ -71,17 +71,20 @@ export default class Line extends Item<LineProps> {
/** /**
* @override * @override
*/ */
public constructor(props: LineProps) { public constructor(props: LineProps, meta: ItemMeta) {
/* /*
* We need to override the constructor cause we need to obtain * We need to override the constructor cause we need to obtain
* the * the
* box size and position from the start and finish points * box size and position from the start and finish points
* of the line. * of the line.
*/ */
super({ super(
...props, {
...Line.extractBoxSizeAndPosition(props) ...props,
}); ...Line.extractBoxSizeAndPosition(props)
},
meta
);
} }
/** /**

View File

@ -1,8 +1,8 @@
import { import {
LinkedVisualConsoleProps, LinkedVisualConsoleProps,
UnknownObject, AnyObject,
WithModuleProps WithModuleProps
} from "../types"; } from "../lib/types";
import { import {
linkedVCPropsDecoder, linkedVCPropsDecoder,
modulePropsDecoder, modulePropsDecoder,
@ -28,7 +28,7 @@ export type ModuleGraphProps = {
* is missing from the raw object or have an invalid type. * is missing from the raw object or have an invalid type.
*/ */
export function moduleGraphPropsDecoder( export function moduleGraphPropsDecoder(
data: UnknownObject data: AnyObject
): ModuleGraphProps | never { ): ModuleGraphProps | never {
if (stringIsEmpty(data.html) && stringIsEmpty(data.encodedHtml)) { if (stringIsEmpty(data.html) && stringIsEmpty(data.encodedHtml)) {
throw new TypeError("missing html content."); throw new TypeError("missing html content.");

View File

@ -2,9 +2,9 @@ import { arc as arcFactory } from "d3-shape";
import { import {
LinkedVisualConsoleProps, LinkedVisualConsoleProps,
UnknownObject, AnyObject,
WithModuleProps WithModuleProps
} from "../types"; } from "../lib/types";
import { import {
linkedVCPropsDecoder, linkedVCPropsDecoder,
modulePropsDecoder, modulePropsDecoder,
@ -81,7 +81,7 @@ function extractValueType(valueType: unknown): PercentileProps["valueType"] {
* is missing from the raw object or have an invalid type. * is missing from the raw object or have an invalid type.
*/ */
export function percentilePropsDecoder( export function percentilePropsDecoder(
data: UnknownObject data: AnyObject
): PercentileProps | never { ): PercentileProps | never {
return { return {
...itemBasePropsDecoder(data), // Object spread. It will merge the properties of the two objects. ...itemBasePropsDecoder(data), // Object spread. It will merge the properties of the two objects.

View File

@ -1,4 +1,4 @@
import { UnknownObject } from "../types"; import { AnyObject } from "../lib/types";
import { import {
stringIsEmpty, stringIsEmpty,
notEmptyStringOr, notEmptyStringOr,
@ -24,7 +24,7 @@ export type ServiceProps = {
* @throws Will throw a TypeError if some property * @throws Will throw a TypeError if some property
* is missing from the raw object or have an invalid type. * is missing from the raw object or have an invalid type.
*/ */
export function servicePropsDecoder(data: UnknownObject): ServiceProps | never { export function servicePropsDecoder(data: AnyObject): ServiceProps | never {
if (data.imageSrc !== null) { if (data.imageSrc !== null) {
if ( if (
typeof data.statusImageSrc !== "string" || typeof data.statusImageSrc !== "string" ||

View File

@ -1,8 +1,8 @@
import { import {
LinkedVisualConsoleProps, LinkedVisualConsoleProps,
UnknownObject, AnyObject,
WithModuleProps WithModuleProps
} from "../types"; } from "../lib/types";
import { import {
linkedVCPropsDecoder, linkedVCPropsDecoder,
parseIntOr, parseIntOr,
@ -69,7 +69,7 @@ const parseProcessValue = (
* is missing from the raw object or have an invalid type. * is missing from the raw object or have an invalid type.
*/ */
export function simpleValuePropsDecoder( export function simpleValuePropsDecoder(
data: UnknownObject data: AnyObject
): SimpleValueProps | never { ): SimpleValueProps | never {
if (typeof data.value !== "string" || data.value.length === 0) { if (typeof data.value !== "string" || data.value.length === 0) {
throw new TypeError("invalid value"); throw new TypeError("invalid value");

View File

@ -1,8 +1,8 @@
import { import {
WithModuleProps, WithModuleProps,
LinkedVisualConsoleProps, LinkedVisualConsoleProps,
UnknownObject AnyObject
} from "../types"; } from "../lib/types";
import { import {
modulePropsDecoder, modulePropsDecoder,
@ -47,7 +47,7 @@ const parseShowLastValueTooltip = (
* is missing from the raw object or have an invalid type. * is missing from the raw object or have an invalid type.
*/ */
export function staticGraphPropsDecoder( export function staticGraphPropsDecoder(
data: UnknownObject data: AnyObject
): StaticGraphProps | never { ): StaticGraphProps | never {
if (typeof data.imageSrc !== "string" || data.imageSrc.length === 0) { if (typeof data.imageSrc !== "string" || data.imageSrc.length === 0) {
throw new TypeError("invalid image src."); throw new TypeError("invalid image src.");

View File

@ -1,4 +1,4 @@
import TypedEvent, { Disposable, Listener } from "../TypedEvent"; import TypedEvent, { Disposable, Listener } from "./TypedEvent";
interface Cancellable { interface Cancellable {
cancel(): void; cancel(): void;

View File

@ -1,12 +1,14 @@
import { import {
UnknownObject, AnyObject,
Position, Position,
Size, Size,
WithAgentProps, WithAgentProps,
WithModuleProps, WithModuleProps,
LinkedVisualConsoleProps, LinkedVisualConsoleProps,
LinkedVisualConsolePropsStatus LinkedVisualConsolePropsStatus,
} from "../types"; UnknownObject,
ItemMeta
} from "./types";
/** /**
* Return a number or a default value from a raw value. * Return a number or a default value from a raw value.
@ -72,6 +74,23 @@ export function parseBoolean(value: unknown): boolean {
else return false; else return false;
} }
/**
* Return a valid date or a default value from a raw value.
* @param value Raw value from which we will try to extract a valid date.
* @param defaultValue Default value to use if we cannot extract a valid date.
* @return A valid date or the default value.
*/
export function parseDateOr<T>(value: unknown, defaultValue: T): Date | T {
if (value instanceof Date) return value;
else if (typeof value === "number") return new Date(value * 1000);
else if (
typeof value === "string" &&
!Number.isNaN(new Date(value).getTime())
)
return new Date(value);
else return defaultValue;
}
/** /**
* Pad the current string with another string (multiple times, if needed) * Pad the current string with another string (multiple times, if needed)
* until the resulting string reaches the given length. * until the resulting string reaches the given length.
@ -113,7 +132,7 @@ export function leftPad(
* @param data Raw object. * @param data Raw object.
* @return An object representing the position. * @return An object representing the position.
*/ */
export function positionPropsDecoder(data: UnknownObject): Position { export function positionPropsDecoder(data: AnyObject): Position {
return { return {
x: parseIntOr(data.x, 0), x: parseIntOr(data.x, 0),
y: parseIntOr(data.y, 0) y: parseIntOr(data.y, 0)
@ -126,7 +145,7 @@ export function positionPropsDecoder(data: UnknownObject): Position {
* @return An object representing the size. * @return An object representing the size.
* @throws Will throw a TypeError if the width and height are not valid numbers. * @throws Will throw a TypeError if the width and height are not valid numbers.
*/ */
export function sizePropsDecoder(data: UnknownObject): Size | never { export function sizePropsDecoder(data: AnyObject): Size | never {
if ( if (
data.width == null || data.width == null ||
isNaN(parseInt(data.width)) || isNaN(parseInt(data.width)) ||
@ -147,7 +166,7 @@ export function sizePropsDecoder(data: UnknownObject): Size | never {
* @param data Raw object. * @param data Raw object.
* @return An object representing the agent properties. * @return An object representing the agent properties.
*/ */
export function agentPropsDecoder(data: UnknownObject): WithAgentProps { export function agentPropsDecoder(data: AnyObject): WithAgentProps {
const agentProps: WithAgentProps = { const agentProps: WithAgentProps = {
agentId: parseIntOr(data.agent, null), agentId: parseIntOr(data.agent, null),
agentName: notEmptyStringOr(data.agentName, null), agentName: notEmptyStringOr(data.agentName, null),
@ -169,7 +188,7 @@ export function agentPropsDecoder(data: UnknownObject): WithAgentProps {
* @param data Raw object. * @param data Raw object.
* @return An object representing the module and agent properties. * @return An object representing the module and agent properties.
*/ */
export function modulePropsDecoder(data: UnknownObject): WithModuleProps { export function modulePropsDecoder(data: AnyObject): WithModuleProps {
return { return {
moduleId: parseIntOr(data.moduleId, null), moduleId: parseIntOr(data.moduleId, null),
moduleName: notEmptyStringOr(data.moduleName, null), moduleName: notEmptyStringOr(data.moduleName, null),
@ -185,7 +204,7 @@ export function modulePropsDecoder(data: UnknownObject): WithModuleProps {
* @throws Will throw a TypeError if the status calculation properties are invalid. * @throws Will throw a TypeError if the status calculation properties are invalid.
*/ */
export function linkedVCPropsDecoder( export function linkedVCPropsDecoder(
data: UnknownObject data: AnyObject
): LinkedVisualConsoleProps | never { ): LinkedVisualConsoleProps | never {
// Object destructuring: http://es6-features.org/#ObjectMatchingShorthandNotation // Object destructuring: http://es6-features.org/#ObjectMatchingShorthandNotation
const { const {
@ -246,6 +265,29 @@ export function linkedVCPropsDecoder(
: linkedLayoutBaseProps; : linkedLayoutBaseProps;
} }
/**
* Build a valid typed object from a raw object.
* @param data Raw object.
* @return An object representing the item's meta properties.
*/
export function itemMetaDecoder(data: UnknownObject): ItemMeta | never {
const receivedAt = parseDateOr(data.receivedAt, null);
if (receivedAt === null) throw new TypeError("invalid meta structure");
let error = null;
if (data.error instanceof Error) error = data.error;
else if (typeof data.error === "string") error = new Error(data.error);
return {
receivedAt,
error,
editMode: parseBoolean(data.editMode),
isFromCache: parseBoolean(data.isFromCache),
isFetching: false,
isUpdating: false
};
}
/** /**
* To get a CSS rule with the most used prefixes. * To get a CSS rule with the most used prefixes.
* @param ruleName Name of the CSS rule. * @param ruleName Name of the CSS rule.

View File

@ -7,7 +7,8 @@ import {
decodeBase64, decodeBase64,
humanDate, humanDate,
humanTime, humanTime,
replaceMacros replaceMacros,
itemMetaDecoder
} from "."; } from ".";
describe("function parseIntOr", () => { describe("function parseIntOr", () => {
@ -72,14 +73,14 @@ describe("function prefixedCssRules", () => {
describe("function decodeBase64", () => { describe("function decodeBase64", () => {
it("should decode the base64 without errors", () => { it("should decode the base64 without errors", () => {
expect(decodeBase64("SGkgSSdtIGRlY29kZWQ=")).toEqual("Hi I'm decoded"); expect(decodeBase64("SGkgSSdtIGRlY29kZWQ=")).toBe("Hi I'm decoded");
expect(decodeBase64("Rk9PQkFSQkFa")).toEqual("FOOBARBAZ"); expect(decodeBase64("Rk9PQkFSQkFa")).toBe("FOOBARBAZ");
expect(decodeBase64("eyJpZCI6MSwibmFtZSI6ImZvbyJ9")).toEqual( expect(decodeBase64("eyJpZCI6MSwibmFtZSI6ImZvbyJ9")).toBe(
'{"id":1,"name":"foo"}' '{"id":1,"name":"foo"}'
); );
expect( expect(
decodeBase64("PGRpdj5Cb3ggPHA+UGFyYWdyYXBoPC9wPjxociAvPjwvZGl2Pg==") decodeBase64("PGRpdj5Cb3ggPHA+UGFyYWdyYXBoPC9wPjxociAvPjwvZGl2Pg==")
).toEqual("<div>Box <p>Paragraph</p><hr /></div>"); ).toBe("<div>Box <p>Paragraph</p><hr /></div>");
}); });
}); });
@ -118,3 +119,46 @@ describe("replaceMacros function", () => {
expect(replaceMacros(macros, text)).toBe("Lorem foo Ipsum baz"); expect(replaceMacros(macros, text)).toBe("Lorem foo Ipsum baz");
}); });
}); });
describe("itemMetaDecoder function", () => {
it("should extract a default meta object", () => {
expect(
itemMetaDecoder({
receivedAt: 1
})
).toEqual({
receivedAt: new Date(1000),
error: null,
isFromCache: false,
isFetching: false,
isUpdating: false,
editMode: false
});
});
it("should extract a valid meta object", () => {
expect(
itemMetaDecoder({
receivedAt: new Date(1000),
error: new Error("foo"),
editMode: 1
})
).toEqual({
receivedAt: new Date(1000),
error: new Error("foo"),
isFromCache: false,
isFetching: false,
isUpdating: false,
editMode: true
});
});
it("should fail when a invalid structure is used", () => {
expect(() => itemMetaDecoder({})).toThrowError(TypeError);
expect(() =>
itemMetaDecoder({
receivedAt: "foo"
})
).toThrowError(TypeError);
});
});

View File

@ -1,7 +1,11 @@
export interface UnknownObject { export interface AnyObject {
[key: string]: any; // eslint-disable-line @typescript-eslint/no-explicit-any [key: string]: any; // eslint-disable-line @typescript-eslint/no-explicit-any
} }
export interface UnknownObject {
[key: string]: unknown;
}
export interface Position { export interface Position {
x: number; x: number;
y: number; y: number;
@ -45,3 +49,12 @@ export type LinkedVisualConsoleProps = {
linkedLayoutId: number | null; linkedLayoutId: number | null;
linkedLayoutAgentId: number | null; linkedLayoutAgentId: number | null;
} & LinkedVisualConsolePropsStatus; } & LinkedVisualConsolePropsStatus;
export interface ItemMeta {
receivedAt: Date;
error: Error | null;
isFromCache: boolean;
isFetching: boolean;
isUpdating: boolean;
editMode: boolean;
}

View File

@ -14,3 +14,8 @@
align-items: center; align-items: center;
user-select: text; user-select: text;
} }
.visual-console-item.is-editing {
border: 2px dashed #33ccff;
transform: translateX(-2px) translateY(-2px);
}