Merge branch 'ent-6782-revision-general-de-la-consola-movil' into 'develop'
SAML login in mobile console See merge request artica/pandorafms!3733
This commit is contained in:
commit
1d6c7c6eed
Binary file not shown.
After Width: | Height: | Size: 8.2 KiB |
|
@ -2252,12 +2252,16 @@ function check_login($output=true)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
include_once $config['homedir'].'/mobile/include/db.class.php';
|
||||||
|
include_once $config['homedir'].'/mobile/include/system.class.php';
|
||||||
include_once $config['homedir'].'/mobile/include/user.class.php';
|
include_once $config['homedir'].'/mobile/include/user.class.php';
|
||||||
|
|
||||||
if (isset($_SESSION['user'])) {
|
if (isset($_SESSION['user'])) {
|
||||||
$user = $_SESSION['user'];
|
$user = User::getInstance();
|
||||||
$id_user = $user->getIdUser();
|
$id_user = $user->getIdUser();
|
||||||
if (is_user($id_user)) {
|
if (is_user($id_user)) {
|
||||||
|
$_SESSION['id_usuario'] = $id_user;
|
||||||
|
$config['id_user'] = $id_user;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1069,6 +1069,16 @@ class Item extends CachedModel
|
||||||
{
|
{
|
||||||
global $config;
|
global $config;
|
||||||
|
|
||||||
|
$mobile_navigation = false;
|
||||||
|
|
||||||
|
if (isset($_SERVER['PHP_SELF']) === true
|
||||||
|
&& (strstr($_SERVER['PHP_SELF'], 'mobile/') !== false
|
||||||
|
|| strstr($_SERVER['HTTP_REFERER'], 'mobile/') !== false)
|
||||||
|
) {
|
||||||
|
$mobile_navigation = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
error_log(obhd($_SERVER['PHP_SELF']));
|
||||||
// Load side libraries.
|
// Load side libraries.
|
||||||
include_once $config['homedir'].'/include/functions_ui.php';
|
include_once $config['homedir'].'/include/functions_ui.php';
|
||||||
if (\is_metaconsole() === true) {
|
if (\is_metaconsole() === true) {
|
||||||
|
@ -1081,6 +1091,7 @@ class Item extends CachedModel
|
||||||
$linkedAgent = static::extractLinkedAgent($data);
|
$linkedAgent = static::extractLinkedAgent($data);
|
||||||
|
|
||||||
$baseUrl = \ui_get_full_url('index.php');
|
$baseUrl = \ui_get_full_url('index.php');
|
||||||
|
$mobileUrl = \ui_get_full_url('mobile/index.php');
|
||||||
|
|
||||||
if ((bool) $data['agentDisabled'] === true
|
if ((bool) $data['agentDisabled'] === true
|
||||||
|| (bool) $data['moduleDisabled'] === true
|
|| (bool) $data['moduleDisabled'] === true
|
||||||
|
@ -1135,6 +1146,15 @@ class Item extends CachedModel
|
||||||
* We are in a regular console.
|
* We are in a regular console.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
if ($mobile_navigation === true) {
|
||||||
|
return $mobileUrl.'?'.http_build_query(
|
||||||
|
[
|
||||||
|
'page' => 'visualmap',
|
||||||
|
'id' => $vcId,
|
||||||
|
]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return $baseUrl.'?'.http_build_query(
|
return $baseUrl.'?'.http_build_query(
|
||||||
[
|
[
|
||||||
'sec' => 'network',
|
'sec' => 'network',
|
||||||
|
@ -1211,6 +1231,15 @@ class Item extends CachedModel
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($mobile_navigation === true) {
|
||||||
|
return $mobileUrl.'?'.http_build_query(
|
||||||
|
[
|
||||||
|
'page' => 'module_graph',
|
||||||
|
'id' => $moduleId,
|
||||||
|
]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return $baseUrl.'?'.http_build_query($queryParams);
|
return $baseUrl.'?'.http_build_query($queryParams);
|
||||||
} else if (\is_metaconsole() === true
|
} else if (\is_metaconsole() === true
|
||||||
&& (bool) \can_user_access_node() === true
|
&& (bool) \can_user_access_node() === true
|
||||||
|
@ -1290,6 +1319,15 @@ class Item extends CachedModel
|
||||||
* We are in a regular console.
|
* We are in a regular console.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
if ($mobile_navigation === true) {
|
||||||
|
return $mobileUrl.'?'.http_build_query(
|
||||||
|
[
|
||||||
|
'page' => 'agent',
|
||||||
|
'id' => $agentId,
|
||||||
|
]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return $baseUrl.'?'.http_build_query(
|
return $baseUrl.'?'.http_build_query(
|
||||||
[
|
[
|
||||||
'sec' => 'estado',
|
'sec' => 'estado',
|
||||||
|
|
|
@ -76,7 +76,7 @@ h1 {
|
||||||
|
|
||||||
.grid-stack-item-content {
|
.grid-stack-item-content {
|
||||||
color: #2c3e50;
|
color: #2c3e50;
|
||||||
/*text-align: center;*/
|
text-align: center;
|
||||||
background-color: #ffffff;
|
background-color: #ffffff;
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
-webkit-box-shadow: 5px 5px 5px 0px rgba(214, 214, 214, 1);
|
-webkit-box-shadow: 5px 5px 5px 0px rgba(214, 214, 214, 1);
|
||||||
|
@ -390,6 +390,7 @@ table.group_modules_status_box tr td > span {
|
||||||
}
|
}
|
||||||
|
|
||||||
table.group_modules_status_box tr td div {
|
table.group_modules_status_box tr td div {
|
||||||
|
background-color: #82b92e;
|
||||||
width: 90%;
|
width: 90%;
|
||||||
padding: 3px;
|
padding: 3px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
@ -543,3 +544,14 @@ div#main_pure {
|
||||||
color: inherit;
|
color: inherit;
|
||||||
font-family: inherit;
|
font-family: inherit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Mobile trick */
|
||||||
|
.ui-mobile-viewport.ui-overlay-c > #main_page > .ui-content {
|
||||||
|
overflow: visible;
|
||||||
|
overflow-x: visible;
|
||||||
|
margin: 0 !important;
|
||||||
|
padding: 0 !important;
|
||||||
|
}
|
||||||
|
.ui-mobile-viewport.ui-overlay-c > #main_page > .ui-content div.label > p {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
|
@ -34,6 +34,12 @@ body {
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
td.flex-center {
|
||||||
|
display: flex !important;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
|
||||||
/*INIT----------Tactical styles-----------------------------------------*/
|
/*INIT----------Tactical styles-----------------------------------------*/
|
||||||
/* Common */
|
/* Common */
|
||||||
|
|
||||||
|
@ -351,6 +357,22 @@ tr.events {
|
||||||
font-size: 12px !important;
|
font-size: 12px !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
table.event_details {
|
||||||
|
height: 14px;
|
||||||
|
color: #424242;
|
||||||
|
}
|
||||||
|
|
||||||
|
table.event_details tr th {
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
table.event_details td:not(:first-child) {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
justify-items: start;
|
||||||
|
}
|
||||||
|
|
||||||
table#list_events th {
|
table#list_events th {
|
||||||
font-size: 12px !important;
|
font-size: 12px !important;
|
||||||
font-weight: bolder !important;
|
font-weight: bolder !important;
|
||||||
|
@ -1274,6 +1296,11 @@ table.tactical_bars {
|
||||||
-webkit-border-radius: 15px !important;
|
-webkit-border-radius: 15px !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.ui-header.ui-bar-a .ui-btn-icon-notext .ui-btn-inner .ui-icon {
|
||||||
|
margin-top: -3px;
|
||||||
|
margin-left: 3.5px;
|
||||||
|
}
|
||||||
|
|
||||||
#login_btn-container .ui-icon {
|
#login_btn-container .ui-icon {
|
||||||
background-color: #333 !important;
|
background-color: #333 !important;
|
||||||
border-radius: 15px !important;
|
border-radius: 15px !important;
|
||||||
|
@ -1354,6 +1381,17 @@ span.nobold * {
|
||||||
display: block !important;
|
display: block !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.status_rounded_rectangles.forced_title {
|
||||||
|
width: 1em;
|
||||||
|
height: 1em;
|
||||||
|
border-radius: 50%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ui-content .ui-listview,
|
||||||
|
.ui-panel-inner > .ui-listview {
|
||||||
|
margin: 0 !important;
|
||||||
|
}
|
||||||
|
|
||||||
#list_Modules *,
|
#list_Modules *,
|
||||||
#list_agent_Modules *,
|
#list_agent_Modules *,
|
||||||
#list_agents *,
|
#list_agents *,
|
||||||
|
@ -1398,7 +1436,7 @@ div.nodata_container {
|
||||||
}
|
}
|
||||||
|
|
||||||
.ui-icon-delete {
|
.ui-icon-delete {
|
||||||
margin-top: -3px !important;
|
margin-top: -3px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.empty_advice {
|
.empty_advice {
|
||||||
|
|
|
@ -151,7 +151,7 @@ class System
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public function getDefaultACLFailText()
|
public static function getDefaultACLFailText()
|
||||||
{
|
{
|
||||||
return __('Access to this page is restricted to authorized users only, please contact your system administrator if you should need help.').'<br><br>'.__('Please remember that any attempts to access this page will be recorded on the %s System Database.', get_product_name());
|
return __('Access to this page is restricted to authorized users only, please contact your system administrator if you should need help.').'<br><br>'.__('Please remember that any attempts to access this page will be recorded on the %s System Database.', get_product_name());
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
<?php
|
<?php
|
||||||
|
// phpcs:disable Squiz.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
|
||||||
// Pandora FMS - http://pandorafms.com
|
// Pandora FMS - http://pandorafms.com
|
||||||
// ==================================================
|
// ==================================================
|
||||||
// Copyright (c) 2005-2021 Artica Soluciones Tecnologicas
|
// Copyright (c) 2005-2021 Artica Soluciones Tecnologicas
|
||||||
|
@ -48,6 +49,20 @@ class Ui
|
||||||
|
|
||||||
private $dialog = '';
|
private $dialog = '';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* List of extra CSS files to be loaded.
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
private $cssList = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* List of extra Javascript files to be loaded.
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
private $jsList = [];
|
||||||
|
|
||||||
|
|
||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
|
@ -777,6 +792,30 @@ class Ui
|
||||||
echo " <script src='../include/javascript/pandora.js'></script>\n";
|
echo " <script src='../include/javascript/pandora.js'></script>\n";
|
||||||
echo " <script src='../include/javascript/pandora_ui.js'></script>\n";
|
echo " <script src='../include/javascript/pandora_ui.js'></script>\n";
|
||||||
|
|
||||||
|
$loaded = [];
|
||||||
|
foreach ($this->cssList as $filename) {
|
||||||
|
if (in_array($filename, $loaded) === true) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
array_push($loaded, $filename);
|
||||||
|
|
||||||
|
$url_css = ui_get_full_url($filename, false, false, false);
|
||||||
|
echo '<link rel="stylesheet" href="'.$url_css.'" type="text/css" />'."\n\t";
|
||||||
|
}
|
||||||
|
|
||||||
|
$js_loaded = [];
|
||||||
|
foreach ($this->jsList as $filename) {
|
||||||
|
if (in_array($filename, $js_loaded) === true) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
array_push($js_loaded, $filename);
|
||||||
|
|
||||||
|
$url_css = ui_get_full_url($filename, false, false, false);
|
||||||
|
echo '<script src="'.$url_css.'" rel="text/javascript"></script>'."\n\t";
|
||||||
|
}
|
||||||
|
|
||||||
echo " </head>\n";
|
echo " </head>\n";
|
||||||
echo " <body>\n";
|
echo " <body>\n";
|
||||||
echo include_javascript_dependencies_flot_graph(false, false);
|
echo include_javascript_dependencies_flot_graph(false, false);
|
||||||
|
@ -857,6 +896,88 @@ class Ui
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add CSS file to be loaded.
|
||||||
|
*
|
||||||
|
* @param string $name Css file name, as in ui_require_css.
|
||||||
|
* @param string $path Path where search for css file.
|
||||||
|
*
|
||||||
|
* @return boolean True if success, False if not.
|
||||||
|
*/
|
||||||
|
public function require_css(
|
||||||
|
string $name,
|
||||||
|
string $path='include/styles/'
|
||||||
|
):bool {
|
||||||
|
$filename = $path.$name.'.css';
|
||||||
|
$system = System::getInstance();
|
||||||
|
|
||||||
|
if (file_exists($filename) === false
|
||||||
|
&& file_exists($system->getConfig('homedir').'/'.$filename) === false
|
||||||
|
&& file_exists($system->getConfig('homedir').'/'.ENTERPRISE_DIR.'/'.$filename) === false
|
||||||
|
) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (in_array($filename, $this->cssList) === false) {
|
||||||
|
$this->cssList[] = $filename;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add JS file to be loaded.
|
||||||
|
*
|
||||||
|
* @param string $name JAvascript file name, as in
|
||||||
|
* \ui_require_javascript_file.
|
||||||
|
* @param string $path Path where search for Javascript file.
|
||||||
|
*
|
||||||
|
* @return boolean True if success, False if not.
|
||||||
|
*/
|
||||||
|
public function require_javascript(
|
||||||
|
string $name,
|
||||||
|
string $path='include/javascript/'
|
||||||
|
):bool {
|
||||||
|
$filename = $path.$name.'.js';
|
||||||
|
$system = System::getInstance();
|
||||||
|
|
||||||
|
if (file_exists($filename) === false
|
||||||
|
&& file_exists($system->getConfig('homedir').'/'.$filename) === false
|
||||||
|
&& file_exists($system->getConfig('homedir').'/'.ENTERPRISE_DIR.'/'.$filename) === false
|
||||||
|
) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (in_array($filename, $this->jsList) === false) {
|
||||||
|
$this->jsList[] = $filename;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Forces reload to retrieve with and height.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function retrieveViewPort()
|
||||||
|
{
|
||||||
|
?>
|
||||||
|
<script type="text/javascript">
|
||||||
|
|
||||||
|
var dimensions = '&width=' + $(window).width();
|
||||||
|
dimensions += '&height=' + $(window).height();
|
||||||
|
window.location.href = window.location.href + dimensions;
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<?php
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class Table
|
class Table
|
||||||
|
|
|
@ -38,8 +38,15 @@ class User
|
||||||
$system = System::getInstance();
|
$system = System::getInstance();
|
||||||
$user = $system->getSession('user', null);
|
$user = $system->getSession('user', null);
|
||||||
|
|
||||||
|
if (is_object($user) === false) {
|
||||||
|
$user = json_decode($user, true);
|
||||||
|
}
|
||||||
|
|
||||||
if (!empty($user)) {
|
if (!empty($user)) {
|
||||||
self::$instance = $user;
|
self::$instance = new self();
|
||||||
|
foreach ($user as $k => $v) {
|
||||||
|
self::$instance->{$k} = $v;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
self::$instance = new self();
|
self::$instance = new self();
|
||||||
}
|
}
|
||||||
|
@ -49,6 +56,12 @@ class User
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public function jsonSerialize()
|
||||||
|
{
|
||||||
|
return get_object_vars($this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public function saveLogin()
|
public function saveLogin()
|
||||||
{
|
{
|
||||||
if ($this->logged) {
|
if ($this->logged) {
|
||||||
|
@ -59,7 +72,7 @@ class User
|
||||||
$config['id_user'] = $this->user;
|
$config['id_user'] = $this->user;
|
||||||
|
|
||||||
$system->setSessionBase('id_usuario', $this->user);
|
$system->setSessionBase('id_usuario', $this->user);
|
||||||
$system->setSession('user', $this);
|
$system->setSession('user', json_encode($this->jsonSerialize()));
|
||||||
|
|
||||||
config_user_set_custom_config();
|
config_user_set_custom_config();
|
||||||
}
|
}
|
||||||
|
@ -86,6 +99,46 @@ class User
|
||||||
{
|
{
|
||||||
$system = System::getInstance();
|
$system = System::getInstance();
|
||||||
|
|
||||||
|
if ($system->getConfig('auth', 'mysql') === 'saml') {
|
||||||
|
if ((bool) $system->getRequest('saml', false) === true) {
|
||||||
|
\enterprise_include_once('include/auth/saml.php');
|
||||||
|
$saml_user_id = enterprise_hook('saml_process_user_login');
|
||||||
|
if (!$saml_user_id) {
|
||||||
|
$this->logged = false;
|
||||||
|
$this->errorLogin = $system->getConfig('auth_error');
|
||||||
|
\enterprise_hook('saml_logout', [true]);
|
||||||
|
} else {
|
||||||
|
$this->logged = true;
|
||||||
|
$this->user = $saml_user_id;
|
||||||
|
$this->loginTime = time();
|
||||||
|
$this->errorLogin = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->saveLogin();
|
||||||
|
return $this->logged;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Maybe back from SAML login.
|
||||||
|
$saml_session = $system->getSession('samlid', null);
|
||||||
|
if ($saml_session !== null) {
|
||||||
|
$this->user = $system->getSession('id_usuario', null);
|
||||||
|
if ($this->user !== null) {
|
||||||
|
$this->loginTime = time();
|
||||||
|
$this->errorLogin = false;
|
||||||
|
$this->logged = true;
|
||||||
|
} else {
|
||||||
|
// SAML Session OK but not in DB.
|
||||||
|
$this->logged = false;
|
||||||
|
$this->errorLogin = __(
|
||||||
|
'User cannot log in into this console, please contact administrator'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->saveLogin();
|
||||||
|
return $this->logged;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (($user == null) && ($password == null)) {
|
if (($user == null) && ($password == null)) {
|
||||||
$user = $system->getRequest('user', null);
|
$user = $system->getRequest('user', null);
|
||||||
$password = $system->getRequest('password', null);
|
$password = $system->getRequest('password', null);
|
||||||
|
@ -205,6 +258,12 @@ class User
|
||||||
|
|
||||||
public function logout()
|
public function logout()
|
||||||
{
|
{
|
||||||
|
$system = System::getInstance();
|
||||||
|
if ($system->getConfig('auth', 'mysql') === 'saml') {
|
||||||
|
\enterprise_include_once('include/auth/saml.php');
|
||||||
|
\enterprise_hook('saml_logout');
|
||||||
|
}
|
||||||
|
|
||||||
$this->user = null;
|
$this->user = null;
|
||||||
$this->logged = false;
|
$this->logged = false;
|
||||||
$this->loginTime = false;
|
$this->loginTime = false;
|
||||||
|
@ -213,7 +272,6 @@ class User
|
||||||
$this->needDoubleAuth = false;
|
$this->needDoubleAuth = false;
|
||||||
$this->errorDoubleAuth = false;
|
$this->errorDoubleAuth = false;
|
||||||
|
|
||||||
$system = System::getInstance();
|
|
||||||
$system->setSession('user', null);
|
$system->setSession('user', null);
|
||||||
$system->sessionDestroy();
|
$system->sessionDestroy();
|
||||||
}
|
}
|
||||||
|
@ -230,7 +288,12 @@ class User
|
||||||
if ($this->errorLogin) {
|
if ($this->errorLogin) {
|
||||||
$options['type'] = 'onStart';
|
$options['type'] = 'onStart';
|
||||||
$options['title_text'] = __('Login Failed');
|
$options['title_text'] = __('Login Failed');
|
||||||
$options['content_text'] = __('User not found in database or incorrect password.');
|
if ($this->errorLogin !== false) {
|
||||||
|
$options['content_text'] = $this->errorLogin;
|
||||||
|
} else {
|
||||||
|
$options['content_text'] = __('User not found in database or incorrect password.');
|
||||||
|
}
|
||||||
|
|
||||||
$ui->addDialog($options);
|
$ui->addDialog($options);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -286,7 +349,29 @@ class User
|
||||||
'name' => 'login_btn',
|
'name' => 'login_btn',
|
||||||
];
|
];
|
||||||
$ui->formAddSubmitButton($options);
|
$ui->formAddSubmitButton($options);
|
||||||
|
|
||||||
$ui->endForm();
|
$ui->endForm();
|
||||||
|
|
||||||
|
if ($system->getConfig('auth', 'mysql') === 'saml') {
|
||||||
|
// Add SAML login button.
|
||||||
|
$ui->beginForm('');
|
||||||
|
$ui->formAddHtml(
|
||||||
|
html_print_input_hidden('action', 'login', true)
|
||||||
|
);
|
||||||
|
$ui->formAddHtml(
|
||||||
|
html_print_input_hidden('saml', '1', true)
|
||||||
|
);
|
||||||
|
$ui->formAddSubmitButton(
|
||||||
|
[
|
||||||
|
'value' => __('Login with SAML'),
|
||||||
|
'icon' => 'arrow-r',
|
||||||
|
'icon_pos' => 'right',
|
||||||
|
'name' => 'login_button_saml',
|
||||||
|
]
|
||||||
|
);
|
||||||
|
$ui->endForm('');
|
||||||
|
}
|
||||||
|
|
||||||
$ui->contentAddHtml('</div>');
|
$ui->contentAddHtml('</div>');
|
||||||
$ui->endContent();
|
$ui->endContent();
|
||||||
$ui->showPage();
|
$ui->showPage();
|
||||||
|
|
|
@ -183,7 +183,6 @@ switch ($action) {
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
|
||||||
break;
|
|
||||||
case 'login':
|
case 'login':
|
||||||
if ($user->login() && $user->isLogged()) {
|
if ($user->login() && $user->isLogged()) {
|
||||||
if (file_exists('../enterprise/load_enterprise.php')) {
|
if (file_exists('../enterprise/load_enterprise.php')) {
|
||||||
|
@ -279,9 +278,6 @@ switch ($action) {
|
||||||
$page = 'events';
|
$page = 'events';
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'Group view':
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'Alert detail':
|
case 'Alert detail':
|
||||||
$page = 'alerts';
|
$page = 'alerts';
|
||||||
break;
|
break;
|
||||||
|
@ -295,6 +291,11 @@ switch ($action) {
|
||||||
$id_map = (int) db_get_value('id', 'tlayout', 'name', $section_data);
|
$id_map = (int) db_get_value('id', 'tlayout', 'name', $section_data);
|
||||||
$_GET['id'] = $id_map;
|
$_GET['id'] = $id_map;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 'Group view':
|
||||||
|
default:
|
||||||
|
// No content.
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -349,6 +350,17 @@ switch ($action) {
|
||||||
$agent = new Agent();
|
$agent = new Agent();
|
||||||
$agent->show();
|
$agent->show();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 'visualmaps':
|
||||||
|
// Show a list of VC.
|
||||||
|
$vc_list = new Visualmaps();
|
||||||
|
$vc_list->show();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'visualmap':
|
||||||
|
$vc = new Visualmap();
|
||||||
|
$vc->show();
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -425,7 +425,12 @@ class Agent
|
||||||
success: function(r) {
|
success: function(r) {
|
||||||
$.mobile.hidePageLoadingMsg();
|
$.mobile.hidePageLoadingMsg();
|
||||||
var className = $('#list_agent_Modules').attr('class');
|
var className = $('#list_agent_Modules').attr('class');
|
||||||
$('#list_agent_Modules').parent().html(r);
|
if (document.getElementById('list_agent_Modules') == null) {
|
||||||
|
$($('p.empty_advice')[0]).parent().html(r);
|
||||||
|
className = 'ui-responsive table-stroke ui-table ui-table-reflow';
|
||||||
|
} else {
|
||||||
|
$('#list_agent_Modules').parent().html(r);
|
||||||
|
}
|
||||||
$('#list_agent_Modules').addClass(className);
|
$('#list_agent_Modules').addClass(className);
|
||||||
},
|
},
|
||||||
error: function(r, t, e) {
|
error: function(r, t, e) {
|
||||||
|
@ -468,7 +473,7 @@ class Agent
|
||||||
'id_agent' => $this->id,
|
'id_agent' => $this->id,
|
||||||
'all_modules' => true,
|
'all_modules' => true,
|
||||||
'status' => -1,
|
'status' => -1,
|
||||||
'name' => $name_filter,
|
'name' => '%'.$name_filter.'%',
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -60,42 +60,51 @@ class Home
|
||||||
'icon' => 'groups',
|
'icon' => 'groups',
|
||||||
];
|
];
|
||||||
|
|
||||||
if (!$system->getConfig('metaconsole')) {
|
if ((bool) $system->getConfig('legacy_vc', false) === false) {
|
||||||
$items['alerts'] = [
|
// Show Visual consoles only if new system is enabled.
|
||||||
'name' => __('Alerts'),
|
$items['visualmaps'] = [
|
||||||
'filename' => 'alerts.php',
|
'name' => __('Visual consoles'),
|
||||||
|
'filename' => 'visualmaps.php',
|
||||||
'menu_item' => true,
|
'menu_item' => true,
|
||||||
'icon' => 'alerts',
|
'icon' => 'visual_console',
|
||||||
];
|
|
||||||
|
|
||||||
$items['agents'] = [
|
|
||||||
'name' => __('Agents'),
|
|
||||||
'filename' => 'agents.php',
|
|
||||||
'menu_item' => true,
|
|
||||||
'icon' => 'agents',
|
|
||||||
];
|
|
||||||
$items['modules'] = [
|
|
||||||
'name' => __('Modules'),
|
|
||||||
'filename' => 'modules.php',
|
|
||||||
'menu_item' => true,
|
|
||||||
'icon' => 'modules',
|
|
||||||
];
|
|
||||||
|
|
||||||
// Not in home.
|
|
||||||
$items['agent'] = [
|
|
||||||
'name' => __('Agent'),
|
|
||||||
'filename' => 'agent.php',
|
|
||||||
'menu_item' => false,
|
|
||||||
'icon' => '',
|
|
||||||
];
|
|
||||||
$items['module_graph'] = [
|
|
||||||
'name' => __('Module graph'),
|
|
||||||
'filename' => 'module_graph.php',
|
|
||||||
'menu_item' => false,
|
|
||||||
'icon' => '',
|
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$items['alerts'] = [
|
||||||
|
'name' => __('Alerts'),
|
||||||
|
'filename' => 'alerts.php',
|
||||||
|
'menu_item' => true,
|
||||||
|
'icon' => 'alerts',
|
||||||
|
];
|
||||||
|
|
||||||
|
$items['agents'] = [
|
||||||
|
'name' => __('Agents'),
|
||||||
|
'filename' => 'agents.php',
|
||||||
|
'menu_item' => true,
|
||||||
|
'icon' => 'agents',
|
||||||
|
];
|
||||||
|
|
||||||
|
$items['modules'] = [
|
||||||
|
'name' => __('Modules'),
|
||||||
|
'filename' => 'modules.php',
|
||||||
|
'menu_item' => true,
|
||||||
|
'icon' => 'modules',
|
||||||
|
];
|
||||||
|
|
||||||
|
// Not in home.
|
||||||
|
$items['agent'] = [
|
||||||
|
'name' => __('Agent'),
|
||||||
|
'filename' => 'agent.php',
|
||||||
|
'menu_item' => false,
|
||||||
|
'icon' => '',
|
||||||
|
];
|
||||||
|
$items['module_graph'] = [
|
||||||
|
'name' => __('Module graph'),
|
||||||
|
'filename' => 'module_graph.php',
|
||||||
|
'menu_item' => false,
|
||||||
|
'icon' => '',
|
||||||
|
];
|
||||||
|
|
||||||
$this->pagesItems = $items;
|
$this->pagesItems = $items;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -154,7 +163,7 @@ class Home
|
||||||
$options = [
|
$options = [
|
||||||
'name' => 'free_search',
|
'name' => 'free_search',
|
||||||
'value' => $this->global_search,
|
'value' => $this->global_search,
|
||||||
'placeholder' => __('Global search'),
|
'placeholder' => __('Agent search'),
|
||||||
];
|
];
|
||||||
$ui->formAddInputSearch($options);
|
$ui->formAddInputSearch($options);
|
||||||
$ui->endForm();
|
$ui->endForm();
|
||||||
|
|
|
@ -1,59 +1,160 @@
|
||||||
<?php
|
<?php
|
||||||
// Pandora FMS - http://pandorafms.com
|
// phpcs:disable Squiz.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
|
||||||
// ==================================================
|
/**
|
||||||
// Copyright (c) 2005-2021 Artica Soluciones Tecnologicas
|
* Visual console mobile viewer class.
|
||||||
// Please see http://pandorafms.org for full contribution list
|
*
|
||||||
// This program is free software; you can redistribute it and/or
|
* @category Mix
|
||||||
// modify it under the terms of the GNU General Public License
|
* @package Pandora FMS
|
||||||
// as published by the Free Software Foundation for version 2.
|
* @subpackage OpenSource
|
||||||
// This program is distributed in the hope that it will be useful,
|
* @version 1.0.0
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* @license See below
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
*
|
||||||
// GNU General Public License for more details.
|
* ______ ___ _______ _______ ________
|
||||||
require_once '../include/functions_visual_map.php';
|
* | __ \.-----.--.--.--| |.-----.----.-----. | ___| | | __|
|
||||||
|
* | __/| _ | | _ || _ | _| _ | | ___| |__ |
|
||||||
|
* |___| |___._|__|__|_____||_____|__| |___._| |___| |__|_|__|_______|
|
||||||
|
*
|
||||||
|
* ============================================================================
|
||||||
|
* Copyright (c) 2005-2019 Artica Soluciones Tecnologicas
|
||||||
|
* Please see http://pandorafms.org for full contribution list
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation for version 2.
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
* ============================================================================
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Begin.
|
||||||
|
require_once '../include/functions_visual_map.php';
|
||||||
|
use Models\VisualConsole\Container as VisualConsole;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Visual console view handler class.
|
||||||
|
*/
|
||||||
class Visualmap
|
class Visualmap
|
||||||
{
|
{
|
||||||
|
|
||||||
private $correct_acl = false;
|
/**
|
||||||
|
* Undocumented variable
|
||||||
|
*
|
||||||
|
* @var boolean
|
||||||
|
*/
|
||||||
|
private $validAcl = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Undocumented variable
|
||||||
|
*
|
||||||
|
* @var boolean
|
||||||
|
*/
|
||||||
private $acl = 'VR';
|
private $acl = 'VR';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Undocumented variable
|
||||||
|
*
|
||||||
|
* @var boolean
|
||||||
|
*/
|
||||||
private $id = 0;
|
private $id = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Undocumented variable
|
||||||
|
*
|
||||||
|
* @var boolean
|
||||||
|
*/
|
||||||
private $visualmap = null;
|
private $visualmap = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* View widh.
|
||||||
|
*
|
||||||
|
* @var integer
|
||||||
|
*/
|
||||||
|
private $width;
|
||||||
|
|
||||||
function __construct()
|
/**
|
||||||
|
* View height.
|
||||||
|
*
|
||||||
|
* @var integer
|
||||||
|
*/
|
||||||
|
private $height;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Rotate view.
|
||||||
|
*
|
||||||
|
* @var boolean
|
||||||
|
*/
|
||||||
|
private $rotate = false;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor.
|
||||||
|
*/
|
||||||
|
public function __construct()
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private function checkVisualmapACL($groupID=0)
|
/**
|
||||||
|
* Verifies ACL access.
|
||||||
|
*
|
||||||
|
* @param integer $groupID Target group id.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
private function checkVisualmapACL(int $groupID=0)
|
||||||
{
|
{
|
||||||
$system = System::getInstance();
|
$system = System::getInstance();
|
||||||
|
|
||||||
if ($system->checkACL($this->acl)) {
|
if ($system->checkACL($this->acl)) {
|
||||||
$this->correct_acl = true;
|
$this->validAcl = true;
|
||||||
} else {
|
} else {
|
||||||
$this->correct_acl = false;
|
$this->validAcl = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve filters.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
private function getFilters()
|
private function getFilters()
|
||||||
{
|
{
|
||||||
$system = System::getInstance();
|
$system = System::getInstance();
|
||||||
|
|
||||||
$this->id = (int) $system->getRequest('id', 0);
|
$this->id = (int) $system->getRequest('id', 0);
|
||||||
|
$this->width = (int) $system->getRequest('width', 0);
|
||||||
|
$this->height = (int) $system->getRequest('height', 0);
|
||||||
|
|
||||||
|
if ($this->width < $this->height) {
|
||||||
|
$w = $this->width;
|
||||||
|
$this->width = $this->height;
|
||||||
|
$this->height = $w;
|
||||||
|
$this->rotate = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Renders the view.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
public function show()
|
public function show()
|
||||||
{
|
{
|
||||||
$this->getFilters();
|
$this->getFilters();
|
||||||
|
|
||||||
|
if (empty($this->width) === true
|
||||||
|
&& empty($this->height) === true
|
||||||
|
) {
|
||||||
|
// Reload forcing user to send width and height.
|
||||||
|
$ui = Ui::getInstance();
|
||||||
|
$ui->retrieveViewPort();
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->height -= 39;
|
||||||
|
|
||||||
$this->visualmap = db_get_row(
|
$this->visualmap = db_get_row(
|
||||||
'tlayout',
|
'tlayout',
|
||||||
'id',
|
'id',
|
||||||
|
@ -65,7 +166,7 @@ class Visualmap
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->checkVisualmapACL($this->visualmap['id_group']);
|
$this->checkVisualmapACL($this->visualmap['id_group']);
|
||||||
if (!$this->correct_acl) {
|
if (!$this->validAcl) {
|
||||||
$this->show_fail_acl();
|
$this->show_fail_acl();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -73,12 +174,25 @@ class Visualmap
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private function show_fail_acl()
|
/**
|
||||||
|
* Shows an error if ACL fails.
|
||||||
|
*
|
||||||
|
* @param string $msg Optional message.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
private function show_fail_acl(string $msg='')
|
||||||
{
|
{
|
||||||
$error['type'] = 'onStart';
|
$error['type'] = 'onStart';
|
||||||
$error['title_text'] = __('You don\'t have access to this page');
|
if (empty($msg) === false) {
|
||||||
$error['content_text'] = System::getDefaultACLFailText();
|
$error['title_text'] = __('Error');
|
||||||
if (class_exists('HomeEnterprise')) {
|
$error['content_text'] = $msg;
|
||||||
|
} else {
|
||||||
|
$error['title_text'] = __('You don\'t have access to this page');
|
||||||
|
$error['content_text'] = System::getDefaultACLFailText();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (class_exists('HomeEnterprise') === true) {
|
||||||
$home = new HomeEnterprise();
|
$home = new HomeEnterprise();
|
||||||
} else {
|
} else {
|
||||||
$home = new Home();
|
$home = new Home();
|
||||||
|
@ -88,11 +202,18 @@ class Visualmap
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public function ajax($parameter2=false)
|
/**
|
||||||
|
* Ajax call manager.
|
||||||
|
*
|
||||||
|
* @param string $parameter2 Not sure why is doing this stuff.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function ajax(string $parameter2='')
|
||||||
{
|
{
|
||||||
$system = System::getInstance();
|
$system = System::getInstance();
|
||||||
$this->checkVisualmapACL($this->visualmap['id_group']);
|
$this->checkVisualmapACL($this->visualmap['id_group']);
|
||||||
if (!$this->correct_acl) {
|
if ((bool) $this->validAcl === false) {
|
||||||
$this->show_fail_acl();
|
$this->show_fail_acl();
|
||||||
} else {
|
} else {
|
||||||
switch ($parameter2) {
|
switch ($parameter2) {
|
||||||
|
@ -100,18 +221,55 @@ class Visualmap
|
||||||
$map_id = $system->getRequest('map_id', '0');
|
$map_id = $system->getRequest('map_id', '0');
|
||||||
$width = $system->getRequest('width', '400');
|
$width = $system->getRequest('width', '400');
|
||||||
$height = $system->getRequest('height', '400');
|
$height = $system->getRequest('height', '400');
|
||||||
visual_map_print_visual_map($map_id, false, true, $width, $height);
|
visual_map_print_visual_map(
|
||||||
|
$map_id,
|
||||||
|
false,
|
||||||
|
true,
|
||||||
|
$width,
|
||||||
|
$height
|
||||||
|
);
|
||||||
|
exit;
|
||||||
|
|
||||||
|
default:
|
||||||
exit;
|
exit;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates HTML code to view target Visual console.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
private function show_visualmap()
|
private function show_visualmap()
|
||||||
{
|
{
|
||||||
$ui = Ui::getInstance();
|
$ui = Ui::getInstance();
|
||||||
$system = System::getInstance();
|
$system = System::getInstance();
|
||||||
|
|
||||||
|
include_once $system->getConfig('homedir').'/vendor/autoload.php';
|
||||||
|
|
||||||
|
// Query parameters.
|
||||||
|
$visualConsoleId = (int) $system->getRequest('id');
|
||||||
|
|
||||||
|
// Refresh interval in seconds.
|
||||||
|
$refr = (int) get_parameter('refr', $system->getConfig('vc_refr'));
|
||||||
|
|
||||||
|
// Check groups can access user.
|
||||||
|
$aclUserGroups = [];
|
||||||
|
if (!users_can_manage_group_all('AR')) {
|
||||||
|
$aclUserGroups = array_keys(users_get_groups(false, 'AR'));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load Visual Console.
|
||||||
|
$visualConsole = null;
|
||||||
|
try {
|
||||||
|
$visualConsole = VisualConsole::fromDB(['id' => $visualConsoleId]);
|
||||||
|
} catch (Throwable $e) {
|
||||||
|
$this->show_fail_acl($e->getMessage());
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
$ui->createPage();
|
$ui->createPage();
|
||||||
$ui->createDefaultHeader(
|
$ui->createDefaultHeader(
|
||||||
sprintf(
|
sprintf(
|
||||||
|
@ -127,61 +285,167 @@ class Visualmap
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
$ui->require_css('visual_maps');
|
||||||
|
$ui->require_css('register');
|
||||||
|
$ui->require_css('dashboards');
|
||||||
|
$ui->require_javascript('pandora_visual_console');
|
||||||
|
$ui->require_javascript('pandora_dashboards');
|
||||||
|
$ui->require_javascript('jquery.cookie');
|
||||||
|
$ui->require_css('modal');
|
||||||
|
$ui->require_css('form');
|
||||||
|
|
||||||
$ui->showFooter(false);
|
$ui->showFooter(false);
|
||||||
$ui->beginContent();
|
$ui->beginContent();
|
||||||
|
|
||||||
ob_start();
|
|
||||||
$rendered_map = '<div id="rendered_visual_map">';
|
|
||||||
$rendered_map .= html_print_image('images/spinner.gif', true);
|
|
||||||
$rendered_map .= '</div>';
|
|
||||||
ob_clean();
|
|
||||||
|
|
||||||
$ui->contentAddHtml($rendered_map);
|
|
||||||
$ui->contentAddHtml(
|
$ui->contentAddHtml(
|
||||||
"<script type=\"text/javascript\">
|
include_javascript_d3(true)
|
||||||
function ajax_load_map() {
|
|
||||||
$('#rendered_visual_map').html('<div class=\"center\"> ".__('Loading...')."<br /><img src=\"images/ajax-loader.gif\" /></div>');
|
|
||||||
|
|
||||||
var map_max_width = window.innerWidth * 0.90;
|
|
||||||
var map_max_height = (window.innerHeight - 47) * 0.90;
|
|
||||||
|
|
||||||
var original_width = ".$this->visualmap['width'].';
|
|
||||||
var original_height = '.$this->visualmap['height'].';
|
|
||||||
|
|
||||||
var map_width = map_max_width;
|
|
||||||
var map_height = original_height / (original_width / map_width);
|
|
||||||
|
|
||||||
if(map_height > map_max_height) {
|
|
||||||
map_height = map_max_height;
|
|
||||||
map_width = original_width / (original_height / map_height);
|
|
||||||
}
|
|
||||||
|
|
||||||
postvars = {};
|
|
||||||
postvars["action"] = "ajax";
|
|
||||||
postvars["parameter1"] = "visualmap";
|
|
||||||
postvars["parameter2"] = "render_map";
|
|
||||||
postvars["map_id"] = "'.$this->id."\";
|
|
||||||
postvars[\"width\"] = map_width;
|
|
||||||
postvars[\"height\"] = map_height;
|
|
||||||
|
|
||||||
$.post(\"index.php\",
|
|
||||||
postvars,
|
|
||||||
function (data) {
|
|
||||||
$('#rendered_visual_map').html(data);
|
|
||||||
},
|
|
||||||
\"html\");
|
|
||||||
}
|
|
||||||
|
|
||||||
ajax_load_map();
|
|
||||||
|
|
||||||
// Detect orientation change to refresh dinamic content
|
|
||||||
$(window).on({
|
|
||||||
orientationchange: function(e) {
|
|
||||||
ajax_load_map();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
</script>"
|
|
||||||
);
|
);
|
||||||
|
|
||||||
|
$size = [
|
||||||
|
'width' => $this->width,
|
||||||
|
'height' => $this->height,
|
||||||
|
];
|
||||||
|
|
||||||
|
$visualConsoleData = $visualConsole->toArray();
|
||||||
|
$ratio_visualconsole = ($visualConsoleData['height'] / $visualConsoleData['width']);
|
||||||
|
$ratio_t = ($size['width'] / $visualConsoleData['width']);
|
||||||
|
$radio_h = ($size['height'] / $visualConsoleData['height']);
|
||||||
|
|
||||||
|
$visualConsoleData['width'] = $size['width'];
|
||||||
|
$visualConsoleData['height'] = ($size['width'] * $ratio_visualconsole);
|
||||||
|
|
||||||
|
if ($visualConsoleData['height'] > $size['height']) {
|
||||||
|
$ratio_t = $radio_h;
|
||||||
|
|
||||||
|
$visualConsoleData['height'] = $size['height'];
|
||||||
|
$visualConsoleData['width'] = ($size['height'] / $ratio_visualconsole);
|
||||||
|
}
|
||||||
|
|
||||||
|
$uniq = uniqid();
|
||||||
|
|
||||||
|
$output = '<div class="container-center" style="position:relative;">';
|
||||||
|
// Style.
|
||||||
|
$style = 'width:'.$visualConsoleData['width'].'px;';
|
||||||
|
$style .= 'height:'.$visualConsoleData['height'].'px;';
|
||||||
|
$style .= 'background-size: cover;';
|
||||||
|
|
||||||
|
// Class.
|
||||||
|
$class = 'visual-console-container-dashboard c-'.$uniq;
|
||||||
|
// Id.
|
||||||
|
$id = 'visual-console-container-'.$uniq;
|
||||||
|
$output .= '<div style="'.$style.'" class="'.$class.'" id="'.$id.'">';
|
||||||
|
$output .= '</div>';
|
||||||
|
$output .= '</div>';
|
||||||
|
|
||||||
|
// Check groups can access user.
|
||||||
|
$aclUserGroups = [];
|
||||||
|
if (users_can_manage_group_all('AR') === true) {
|
||||||
|
$aclUserGroups = array_keys(
|
||||||
|
users_get_groups(false, 'AR')
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
$ignored_params['refr'] = '';
|
||||||
|
\ui_require_javascript_file(
|
||||||
|
'tiny_mce',
|
||||||
|
'include/javascript/tiny_mce/'
|
||||||
|
);
|
||||||
|
\ui_require_javascript_file(
|
||||||
|
'pandora_visual_console',
|
||||||
|
'include/javascript/',
|
||||||
|
true
|
||||||
|
);
|
||||||
|
\include_javascript_d3();
|
||||||
|
\visual_map_load_client_resources();
|
||||||
|
|
||||||
|
// Load Visual Console Items.
|
||||||
|
$visualConsoleItems = VisualConsole::getItemsFromDB(
|
||||||
|
$visualConsoleId,
|
||||||
|
$aclUserGroups,
|
||||||
|
$ratio_t
|
||||||
|
);
|
||||||
|
|
||||||
|
// Horrible trick! due to the use of tinyMCE
|
||||||
|
// it is necessary to modify specific classes of each
|
||||||
|
// of the visual consoles.
|
||||||
|
$output .= '<style type="text/css">';
|
||||||
|
$output .= '.c-'.$uniq.', .c-'.$uniq.' *:not(.parent_graph p table tr td span) { font-size: '.(8 * $ratio_t).'pt; line-height:'.(8 * ($ratio_t) * 1.5).'pt; }';
|
||||||
|
$output .= '.c-'.$uniq.' .visual_font_size_4pt, .c-'.$uniq.' .visual_font_size_4pt * { font-size: '.(4 * $ratio_t).'pt; line-height:'.(4 * ($ratio_t)).'pt; }';
|
||||||
|
$output .= '.c-'.$uniq.' .visual_font_size_6pt, .c-'.$uniq.' .visual_font_size_6pt * { font-size: '.(6 * $ratio_t).'pt; line-height:'.(6 * ($ratio_t)).'pt; }';
|
||||||
|
$output .= '.c-'.$uniq.' .visual_font_size_8pt, .c-'.$uniq.' .visual_font_size_8pt * { font-size: '.(8 * $ratio_t).'pt; line-height:'.(8 * ($ratio_t)).'pt; }';
|
||||||
|
$output .= '.c-'.$uniq.' .visual_font_size_10pt, .c-'.$uniq.' .visual_font_size_10pt * { font-size: '.(10 * $ratio_t).'pt; line-height:'.(10 * ($ratio_t)).'pt; }';
|
||||||
|
$output .= '.c-'.$uniq.' .visual_font_size_12pt, .c-'.$uniq.' .visual_font_size_12pt * { font-size: '.(12 * $ratio_t).'pt; line-height:'.(12 * ($ratio_t)).'pt; }';
|
||||||
|
$output .= '.c-'.$uniq.' .visual_font_size_14pt, .c-'.$uniq.' .visual_font_size_14pt * { font-size: '.(14 * $ratio_t).'pt; line-height:'.(14 * ($ratio_t)).'pt; }';
|
||||||
|
$output .= '.c-'.$uniq.' .visual_font_size_18pt, .c-'.$uniq.' .visual_font_size_18pt * { font-size: '.(18 * $ratio_t).'pt; line-height:'.(18 * ($ratio_t)).'pt; }';
|
||||||
|
$output .= '.c-'.$uniq.' .visual_font_size_24pt, .c-'.$uniq.' .visual_font_size_24pt * { font-size: '.(24 * $ratio_t).'pt; line-height:'.(24 * ($ratio_t)).'pt; }';
|
||||||
|
$output .= '.c-'.$uniq.' .visual_font_size_28pt, .c-'.$uniq.' .visual_font_size_28pt * { font-size: '.(28 * $ratio_t).'pt; line-height:'.(28 * ($ratio_t)).'pt; }';
|
||||||
|
$output .= '.c-'.$uniq.' .visual_font_size_36pt, .c-'.$uniq.' .visual_font_size_36pt * { font-size: '.(36 * $ratio_t).'pt; line-height:'.(36 * ($ratio_t)).'pt; }';
|
||||||
|
$output .= '.c-'.$uniq.' .visual_font_size_48pt, .c-'.$uniq.' .visual_font_size_48pt * { font-size: '.(48 * $ratio_t).'pt; line-height:'.(48 * ($ratio_t)).'pt; }';
|
||||||
|
$output .= '.c-'.$uniq.' .visual_font_size_60pt, .c-'.$uniq.' .visual_font_size_60pt * { font-size: '.(60 * $ratio_t).'pt; line-height:'.(60 * ($ratio_t)).'pt; }';
|
||||||
|
$output .= '.c-'.$uniq.' .visual_font_size_72pt, .c-'.$uniq.' .visual_font_size_72pt * { font-size: '.(72 * $ratio_t).'pt; line-height:'.(72 * ($ratio_t)).'pt; }';
|
||||||
|
$output .= '.c-'.$uniq.' .visual_font_size_84pt, .c-'.$uniq.' .visual_font_size_84pt * { font-size: '.(84 * $ratio_t).'pt; line-height:'.(84 * ($ratio_t)).'pt; }';
|
||||||
|
$output .= '.c-'.$uniq.' .visual_font_size_96pt, .c-'.$uniq.' .visual_font_size_96pt * { font-size: '.(96 * $ratio_t).'pt; line-height:'.(96 * ($ratio_t)).'pt; }';
|
||||||
|
$output .= '.c-'.$uniq.' .visual_font_size_116pt, .c-'.$uniq.' .visual_font_size_116pt * { font-size: '.(116 * $ratio_t).'pt; line-height:'.(116 * ($ratio_t)).'pt; }';
|
||||||
|
$output .= '.c-'.$uniq.' .visual_font_size_128pt, .c-'.$uniq.' .visual_font_size_128pt * { font-size: '.(128 * $ratio_t).'pt; line-height:'.(128 * ($ratio_t)).'pt; }';
|
||||||
|
$output .= '.c-'.$uniq.' .visual_font_size_140pt, .c-'.$uniq.' .visual_font_size_140pt * { font-size: '.(140 * $ratio_t).'pt; line-height:'.(140 * ($ratio_t)).'pt; }';
|
||||||
|
$output .= '.c-'.$uniq.' .visual_font_size_154pt, .c-'.$uniq.' .visual_font_size_154pt * { font-size: '.(154 * $ratio_t).'pt; line-height:'.(154 * ($ratio_t)).'pt; }';
|
||||||
|
$output .= '.c-'.$uniq.' .visual_font_size_196pt, .c-'.$uniq.' .visual_font_size_196pt * { font-size: '.(196 * $ratio_t).'pt; line-height:'.(196 * ($ratio_t)).'pt; }';
|
||||||
|
$output .= '.c-'.$uniq.' .flot-text, .c-'.$uniq.' .flot-text * { font-size: '.(8 * $ratio_t).'pt !important; line-height:'.(8 * ($ratio_t)).'pt !important; }';
|
||||||
|
$output .= '.c-'.$uniq.' .visual-console-item .digital-clock span.time {font-size: '.(50 * $ratio_t).'px !important; line-height: '.(50 * $ratio_t).'px !important;}';
|
||||||
|
$output .= '.c-'.$uniq.' .visual-console-item .digital-clock span.date {font-size: '.(25 * $ratio_t).'px !important; line-height: '.(25 * $ratio_t).'px !important;}';
|
||||||
|
$output .= '.c-'.$uniq.' .visual-console-item .digital-clock span.timezone {font-size: '.(25 * $ratio_t).'px !important; line-height: '.(25 * $ratio_t).'px !important;}';
|
||||||
|
$output .= '.c-'.$uniq.' .visual-console-item .donut-graph * {font-size: '.(8 * $ratio_t).'px !important; line-height: '.(8 * $ratio_t).'px !important;}';
|
||||||
|
$output .= '.c-'.$uniq.' .visual-console-item .donut-graph g rect {width:'.(25 * $ratio_t).' !important; height: '.(15 * $ratio_t).' !important;}';
|
||||||
|
$output .= '</style>';
|
||||||
|
|
||||||
|
$visualConsoleItems = array_reduce(
|
||||||
|
$visualConsoleItems,
|
||||||
|
function ($carry, $item) use ($ratio_t) {
|
||||||
|
$carry[] = $item->toArray();
|
||||||
|
return $carry;
|
||||||
|
},
|
||||||
|
[]
|
||||||
|
);
|
||||||
|
|
||||||
|
$settings = \json_encode(
|
||||||
|
[
|
||||||
|
'props' => $visualConsoleData,
|
||||||
|
'items' => $visualConsoleItems,
|
||||||
|
'baseUrl' => ui_get_full_url('/', false, false, false),
|
||||||
|
'ratio' => $ratio_t,
|
||||||
|
'size' => $size,
|
||||||
|
'cellId' => $uniq,
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
$output .= '<script type="text/javascript">';
|
||||||
|
$output .= '$(document).ready(function () {';
|
||||||
|
$output .= 'dashboardLoadVC('.$settings.')';
|
||||||
|
$output .= '});';
|
||||||
|
if ($this->rotate === true) {
|
||||||
|
$output .= "$('.container-center').css('transform', 'rotate(90deg)');";
|
||||||
|
}
|
||||||
|
|
||||||
|
$output .= '$( window ).on( "orientationchange", function( event )';
|
||||||
|
$output .= ' { window.location.href = "';
|
||||||
|
$output .= ui_get_full_url(
|
||||||
|
'/mobile/index.php?page=visualmap&id='.$visualConsoleId
|
||||||
|
);
|
||||||
|
$output .= '" });';
|
||||||
|
|
||||||
|
$output .= '</script>';
|
||||||
|
|
||||||
|
$ui->contentAddHtml($output);
|
||||||
|
|
||||||
|
// Load Visual Console Items.
|
||||||
|
$visualConsoleItems = VisualConsole::getItemsFromDB(
|
||||||
|
$visualConsoleId,
|
||||||
|
$aclUserGroups
|
||||||
|
);
|
||||||
|
|
||||||
|
$javascript = ob_get_clean();
|
||||||
|
$ui->contentAddHtml($javascript);
|
||||||
|
|
||||||
$ui->endContent();
|
$ui->endContent();
|
||||||
$ui->showPage();
|
$ui->showPage();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,56 +1,107 @@
|
||||||
<?php
|
<?php
|
||||||
// Pandora FMS - http://pandorafms.com
|
// phpcs:disable Squiz.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
|
||||||
// ==================================================
|
/**
|
||||||
// Copyright (c) 2005-2021 Artica Soluciones Tecnologicas
|
* List of visual consoles, for mobile view.
|
||||||
// Please see http://pandorafms.org for full contribution list
|
*
|
||||||
// This program is free software; you can redistribute it and/or
|
* @category Common Class
|
||||||
// modify it under the terms of the GNU General Public License
|
* @package Pandora FMS
|
||||||
// as published by the Free Software Foundation for version 2.
|
* @subpackage OpenSource
|
||||||
// This program is distributed in the hope that it will be useful,
|
* @version 1.0.0
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* @license See below
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
*
|
||||||
// GNU General Public License for more details.
|
* ______ ___ _______ _______ ________
|
||||||
|
* | __ \.-----.--.--.--| |.-----.----.-----. | ___| | | __|
|
||||||
|
* | __/| _ | | _ || _ | _| _ | | ___| |__ |
|
||||||
|
* |___| |___._|__|__|_____||_____|__| |___._| |___| |__|_|__|_______|
|
||||||
|
*
|
||||||
|
* ============================================================================
|
||||||
|
* Copyright (c) 2005-2019 Artica Soluciones Tecnologicas
|
||||||
|
* Please see http://pandorafms.org for full contribution list
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation for version 2.
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
* ============================================================================
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Begin.
|
||||||
ob_start();
|
ob_start();
|
||||||
require_once '../include/functions_visual_map.php';
|
require_once '../include/functions_visual_map.php';
|
||||||
ob_get_clean();
|
ob_get_clean();
|
||||||
// Fixed unused javascript code.
|
// Fixed unused javascript code.
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class to generate a list of current visual consoles defined.
|
||||||
|
*/
|
||||||
class Visualmaps
|
class Visualmaps
|
||||||
{
|
{
|
||||||
|
|
||||||
private $correct_acl = false;
|
/**
|
||||||
|
* ACL allowed.
|
||||||
|
*
|
||||||
|
* @var boolean
|
||||||
|
*/
|
||||||
|
private $allowed = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Perms needed to access this feature.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
private $acl = 'VR';
|
private $acl = 'VR';
|
||||||
|
|
||||||
private $default = true;
|
/**
|
||||||
|
* Default filters.
|
||||||
private $default_filters = [];
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
private $defaultFilters = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Group.
|
||||||
|
*
|
||||||
|
* @var integer
|
||||||
|
*/
|
||||||
private $group = 0;
|
private $group = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Type. Something about filtering.
|
||||||
|
*
|
||||||
|
* @var boolean
|
||||||
|
*/
|
||||||
private $type = 0;
|
private $type = 0;
|
||||||
|
|
||||||
private $list_types = null;
|
|
||||||
|
|
||||||
|
/**
|
||||||
function __construct()
|
* Builder.
|
||||||
|
*/
|
||||||
|
public function __construct()
|
||||||
{
|
{
|
||||||
$system = System::getInstance();
|
$system = System::getInstance();
|
||||||
|
|
||||||
if ($system->checkACL($this->acl)) {
|
if ($system->checkACL($this->acl)) {
|
||||||
$this->correct_acl = true;
|
$this->allowed = true;
|
||||||
} else {
|
} else {
|
||||||
$this->correct_acl = false;
|
$this->allowed = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prepare filters for current view.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
private function getFilters()
|
private function getFilters()
|
||||||
{
|
{
|
||||||
$system = System::getInstance();
|
$system = System::getInstance();
|
||||||
$user = User::getInstance();
|
$user = User::getInstance();
|
||||||
|
|
||||||
$this->default_filters['group'] = true;
|
$this->defaultFilters['group'] = true;
|
||||||
$this->default_filters['type'] = true;
|
$this->defaultFilters['type'] = true;
|
||||||
|
|
||||||
$this->group = (int) $system->getRequest('group', __('Group'));
|
$this->group = (int) $system->getRequest('group', __('Group'));
|
||||||
if (!$user->isInGroup($this->acl, $this->group)) {
|
if (!$user->isInGroup($this->acl, $this->group)) {
|
||||||
|
@ -61,7 +112,7 @@ class Visualmaps
|
||||||
$this->group = 0;
|
$this->group = 0;
|
||||||
} else {
|
} else {
|
||||||
$this->default = false;
|
$this->default = false;
|
||||||
$this->default_filters['group'] = false;
|
$this->defaultFilters['group'] = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->type = $system->getRequest('type', __('Type'));
|
$this->type = $system->getRequest('type', __('Type'));
|
||||||
|
@ -69,14 +120,19 @@ class Visualmaps
|
||||||
$this->type = '0';
|
$this->type = '0';
|
||||||
} else {
|
} else {
|
||||||
$this->default = false;
|
$this->default = false;
|
||||||
$this->default_filters['type'] = false;
|
$this->defaultFilters['type'] = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Run view.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
public function show()
|
public function show()
|
||||||
{
|
{
|
||||||
if (!$this->correct_acl) {
|
if (!$this->allowed) {
|
||||||
$this->show_fail_acl();
|
$this->show_fail_acl();
|
||||||
} else {
|
} else {
|
||||||
$this->getFilters();
|
$this->getFilters();
|
||||||
|
@ -85,12 +141,19 @@ class Visualmaps
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show a message about failed ACL access.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
private function show_fail_acl()
|
private function show_fail_acl()
|
||||||
{
|
{
|
||||||
$error['type'] = 'onStart';
|
$error['type'] = 'onStart';
|
||||||
$error['title_text'] = __('You don\'t have access to this page');
|
$error['title_text'] = __('You don\'t have access to this page');
|
||||||
$error['content_text'] = System::getDefaultACLFailText();
|
$error['content_text'] = System::getDefaultACLFailText();
|
||||||
if (class_exists('HomeEnterprise')) {
|
|
||||||
|
// Redirect to main page.
|
||||||
|
if (class_exists('HomeEnterprise') === true) {
|
||||||
$home = new HomeEnterprise();
|
$home = new HomeEnterprise();
|
||||||
} else {
|
} else {
|
||||||
$home = new Home();
|
$home = new Home();
|
||||||
|
@ -100,6 +163,11 @@ class Visualmaps
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show visual console list header.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
private function show_visualmaps()
|
private function show_visualmaps()
|
||||||
{
|
{
|
||||||
$ui = Ui::getInstance();
|
$ui = Ui::getInstance();
|
||||||
|
@ -124,57 +192,44 @@ class Visualmaps
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show list of visual consoles.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
private function listVisualmapsHtml()
|
private function listVisualmapsHtml()
|
||||||
{
|
{
|
||||||
$system = System::getInstance();
|
$system = System::getInstance();
|
||||||
$ui = Ui::getInstance();
|
$ui = Ui::getInstance();
|
||||||
|
|
||||||
// Create filter
|
$visualmaps = visual_map_get_user_layouts();
|
||||||
$where = [];
|
|
||||||
// Order by type field
|
|
||||||
$where['order'] = 'type';
|
|
||||||
|
|
||||||
if ($this->group != '0') {
|
if (empty($visualmaps) === true) {
|
||||||
$where['id_group'] = $this->group;
|
$ui->contentAddHtml('<p style="color: #ff0000;">'.__('No maps defined').'</p>');
|
||||||
}
|
|
||||||
|
|
||||||
if ($this->type != '0') {
|
|
||||||
$where['type'] = $this->type;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Only display maps of "All" group if user is administrator
|
|
||||||
// or has "RR" privileges, otherwise show only maps of user group
|
|
||||||
$id_user = $system->getConfig('id_user');
|
|
||||||
$own_info = get_user_info($id_user);
|
|
||||||
if ($own_info['is_admin'] || $system->checkACL($this->acl)) {
|
|
||||||
$maps = visual_map_get_user_layouts();
|
|
||||||
} else {
|
|
||||||
$maps = visual_map_get_user_layouts($id_user, false, false, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (empty($maps)) {
|
|
||||||
$maps = [];
|
|
||||||
}
|
|
||||||
|
|
||||||
$list = [];
|
|
||||||
foreach ($maps as $map) {
|
|
||||||
$row = [];
|
|
||||||
$row[__('Name')] = '<a class="ui-link" data-ajax="false" href="index.php?page=visualmap&id='.$map['id'].'">'.io_safe_output($map['name']).'</a>';
|
|
||||||
// $row[__('Type')] = $map['type'];
|
|
||||||
$row[__('Group')] = ui_print_group_icon($map['id_group'], true, 'groups_small', '', false);
|
|
||||||
$list[] = $row;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (count($maps) == 0) {
|
|
||||||
$ui->contentAddHtml('<p class="color_ff0">'.__('No maps defined').'</p>');
|
|
||||||
} else {
|
} else {
|
||||||
$table = new Table();
|
$table = new Table();
|
||||||
|
// Without header jquery.mobile crashes.
|
||||||
|
$table->addHeader(['']);
|
||||||
$table->id = 'list_visualmaps';
|
$table->id = 'list_visualmaps';
|
||||||
$table->importFromHash($list);
|
foreach ($visualmaps as $map) {
|
||||||
$ui->contentAddHtml($table->getHTML());
|
$link = '<a class="ui-link" data-ajax="false" ';
|
||||||
}
|
$link .= ' href="index.php?page=visualmap&id=';
|
||||||
|
$link .= $map['id'].'">'.io_safe_output($map['name']).'</a>';
|
||||||
|
|
||||||
$ui->contentAddLinkListener('list_visualmaps');
|
$row = $link;
|
||||||
|
$row .= ui_print_group_icon(
|
||||||
|
$map['id_group'],
|
||||||
|
true,
|
||||||
|
'groups_small',
|
||||||
|
'',
|
||||||
|
false
|
||||||
|
);
|
||||||
|
$table->addRow([ $map['id'].' flex-center' => $row]);
|
||||||
|
}
|
||||||
|
|
||||||
|
$ui->contentAddHtml($table->getHTML());
|
||||||
|
$ui->contentAddLinkListener('list_visualmaps');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue