diff --git a/pandora_console/images/tree_events.png b/pandora_console/images/tree_events.png
new file mode 100644
index 0000000000..7628d6a80d
Binary files /dev/null and b/pandora_console/images/tree_events.png differ
diff --git a/pandora_console/images/tree_service_map.png b/pandora_console/images/tree_service_map.png
new file mode 100644
index 0000000000..16005f1c98
Binary files /dev/null and b/pandora_console/images/tree_service_map.png differ
diff --git a/pandora_console/include/ajax/tree.ajax.php b/pandora_console/include/ajax/tree.ajax.php
index 6c8365a924..21df029b0a 100644
--- a/pandora_console/include/ajax/tree.ajax.php
+++ b/pandora_console/include/ajax/tree.ajax.php
@@ -3,173 +3,163 @@
 // ==================================================
 // Copyright (c) 2005-2012 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 Lesser General Public License
 // as published by the Free Software Foundation; 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.
+
 // Only accesible by ajax
-if (is_ajax()) {
-    global $config;
+if (is_ajax ()) {
+	global $config;
+	
+	enterprise_include_once("include/functions_dashboard.php");
 
-    enterprise_include_once('include/functions_dashboard.php');
+	$public_hash = get_parameter('hash', 0);
 
-    $public_hash = get_parameter('hash', 0);
+	// Try to authenticate by hash on public dashboards
+	if ($public_hash == 0) {
+		// Login check
+		check_login();
+	} else {
+		$validate_hash = enterprise_hook(
+			'dasboard_validate_public_hash',
+			array($public_hash, 'tree_view')
+		);
+		if ($validate_hash === false || $validate_hash === ENTERPRISE_NOT_HOOK) {
+			db_pandora_audit("Invalid public hash",	"Trying to access report builder");
+			require ("general/noaccess.php");
+			exit;
+		}
+	}
+	
+	require_once($config['homedir'] . "/include/class/Tree.class.php");
+	require_once($config['homedir'] . "/include/class/TreeOS.class.php");
+	require_once($config['homedir'] . "/include/class/TreeModuleGroup.class.php");
+	require_once($config['homedir'] . "/include/class/TreeModule.class.php");
+	require_once($config['homedir'] . "/include/class/TreeTag.class.php");
+	require_once($config['homedir'] . "/include/class/TreeGroup.class.php");
+	require_once($config['homedir'] . "/include/class/TreeService.class.php");
+	require_once($config['homedir'] . "/include/class/TreeGroupEdition.class.php");
+	enterprise_include_once("include/class/TreePolicies.class.php");
+	enterprise_include_once("include/class/TreeGroupMeta.class.php");
+	require_once($config['homedir'] . "/include/functions_reporting.php");
+	require_once($config['homedir'] . "/include/functions_os.php");
+	
+	$getChildren = (bool) get_parameter('getChildren', 0);
+	$getGroupStatus = (bool) get_parameter('getGroupStatus', 0);
+	$getDetail = (bool) get_parameter('getDetail');
+	
+	if ($getChildren) {
+		$type = get_parameter('type', 'group');
+		$rootType = get_parameter('rootType', '');
+		$id = get_parameter('id', -1);
+		$rootID = get_parameter('rootID', -1);
+		$serverID = get_parameter('serverID', false);
+		$childrenMethod = get_parameter('childrenMethod', 'on_demand');
+		$hash = get_parameter('hash', false);
+		if ($hash !== false) {
+			enterprise_hook('dasboard_validate_public_hash', array($hash, 'tree_view'));
+		}
 
-    // Try to authenticate by hash on public dashboards
-    if ($public_hash == 0) {
-        // Login check
-        check_login();
-    } else {
-        $validate_hash = enterprise_hook(
-            'dasboard_validate_public_hash',
-            [
-                $public_hash,
-                'tree_view',
-            ]
-        );
-        if ($validate_hash === false || $validate_hash === ENTERPRISE_NOT_HOOK) {
-            db_pandora_audit('Invalid public hash', 'Trying to access report builder');
-            include 'general/noaccess.php';
-            exit;
-        }
-    }
+		$default_filters = array(
+				'searchAgent' => '',
+				'statusAgent' => AGENT_STATUS_ALL,
+				'searchModule' => '',
+				'statusModule' => -1,
+				'groupID' => 0,
+				'tagID' => 0,
+			);
+		$filter = get_parameter('filter', $default_filters);
 
-    include_once $config['homedir'].'/include/class/Tree.class.php';
-    include_once $config['homedir'].'/include/class/TreeOS.class.php';
-    include_once $config['homedir'].'/include/class/TreeModuleGroup.class.php';
-    include_once $config['homedir'].'/include/class/TreeModule.class.php';
-    include_once $config['homedir'].'/include/class/TreeTag.class.php';
-    include_once $config['homedir'].'/include/class/TreeGroup.class.php';
-    include_once $config['homedir'].'/include/class/TreeGroupEdition.class.php';
-    enterprise_include_once('include/class/TreePolicies.class.php');
-    enterprise_include_once('include/class/TreeGroupMeta.class.php');
-    include_once $config['homedir'].'/include/functions_reporting.php';
-    include_once $config['homedir'].'/include/functions_os.php';
+		$agent_a = check_acl ($config['id_user'], 0, "AR");
+		$agent_w = check_acl ($config['id_user'], 0, "AW");
+		$access = ($agent_a == true) ? 'AR' : (($agent_w == true) ? 'AW' : 'AR');
+		$switch_type = !empty($rootType) ? $rootType : $type;
+		switch ($switch_type) {
+			case 'os':
+				$tree = new TreeOS($type, $rootType, $id, $rootID, $serverID, $childrenMethod, $access);
+				break;
+			case 'module_group':
+				$tree = new TreeModuleGroup($type, $rootType, $id, $rootID, $serverID, $childrenMethod, $access);
+				break;
+			case 'module':
+				$tree = new TreeModule($type, $rootType, $id, $rootID, $serverID, $childrenMethod, $access);
+				break;
+			case 'tag':
+				$tree = new TreeTag($type, $rootType, $id, $rootID, $serverID, $childrenMethod, $access);
+				break;
+			case 'group':
+				if(is_metaconsole()){
+					if (!class_exists('TreeGroupMeta')) break;
+					$tree = new TreeGroupMeta($type, $rootType, $id, $rootID, $serverID, $childrenMethod, $access);
+				}
+				else{
+					$tree = new TreeGroup($type, $rootType, $id, $rootID, $serverID, $childrenMethod, $access);
+				}
+				break;
+			case 'policies':
+				if (!class_exists('TreePolicies')) break;
+				$tree = new TreePolicies($type, $rootType, $id, $rootID, $serverID, $childrenMethod, $access);
+				break;
+			case 'group_edition':
+				$tree = new TreeGroupEdition($type, $rootType, $id, $rootID, $serverID, $childrenMethod, $access);
+				break;
+			case 'services':
+				$tree = new TreeService($type, $rootType, $id, $rootID, $serverID, $childrenMethod, $access);
+				break;
+			default:
+				// FIXME. No error handler
+				return;
+		}
 
-    $getChildren = (bool) get_parameter('getChildren', 0);
-    $getGroupStatus = (bool) get_parameter('getGroupStatus', 0);
-    $getDetail = (bool) get_parameter('getDetail');
+		$tree->setFilter($filter);
+		ob_clean();
 
-    if ($getChildren) {
-        $type = get_parameter('type', 'group');
-        $rootType = get_parameter('rootType', '');
-        $id = get_parameter('id', -1);
-        $rootID = get_parameter('rootID', -1);
-        $serverID = get_parameter('serverID', false);
-        $childrenMethod = get_parameter('childrenMethod', 'on_demand');
-        $hash = get_parameter('hash', false);
-        if ($hash !== false) {
-            enterprise_hook('dasboard_validate_public_hash', [$hash, 'tree_view']);
-        }
-
-        $default_filters = [
-            'searchAgent'  => '',
-            'statusAgent'  => AGENT_STATUS_ALL,
-            'searchModule' => '',
-            'statusModule' => -1,
-            'groupID'      => 0,
-            'tagID'        => 0,
-        ];
-        $filter = get_parameter('filter', $default_filters);
-
-        $agent_a = check_acl($config['id_user'], 0, 'AR');
-        $agent_w = check_acl($config['id_user'], 0, 'AW');
-        $access = ($agent_a == true) ? 'AR' : (($agent_w == true) ? 'AW' : 'AR');
-        $switch_type = !empty($rootType) ? $rootType : $type;
-        switch ($switch_type) {
-            case 'os':
-                $tree = new TreeOS($type, $rootType, $id, $rootID, $serverID, $childrenMethod, $access);
-            break;
-
-            case 'module_group':
-                $tree = new TreeModuleGroup($type, $rootType, $id, $rootID, $serverID, $childrenMethod, $access);
-            break;
-
-            case 'module':
-                $tree = new TreeModule($type, $rootType, $id, $rootID, $serverID, $childrenMethod, $access);
-            break;
-
-            case 'tag':
-                $tree = new TreeTag($type, $rootType, $id, $rootID, $serverID, $childrenMethod, $access);
-            break;
-
-            case 'group':
-                if (is_metaconsole()) {
-                    if (!class_exists('TreeGroupMeta')) {
-                        break;
-                    }
-
-                    $tree = new TreeGroupMeta($type, $rootType, $id, $rootID, $serverID, $childrenMethod, $access);
-                } else {
-                    $tree = new TreeGroup($type, $rootType, $id, $rootID, $serverID, $childrenMethod, $access);
-                }
-            break;
-
-            case 'policies':
-                if (!class_exists('TreePolicies')) {
-                    break;
-                }
-
-                $tree = new TreePolicies($type, $rootType, $id, $rootID, $serverID, $childrenMethod, $access);
-            break;
-
-            case 'group_edition':
-                $tree = new TreeGroupEdition($type, $rootType, $id, $rootID, $serverID, $childrenMethod, $access);
-            break;
-
-            default:
-                // FIXME. No error handler
-            return;
-        }
-
-        $tree->setFilter($filter);
-        ob_clean();
-        echo json_encode(['success' => 1, 'tree' => $tree->getArray()]);
-        return;
-    }
-
-    if ($getDetail) {
-        include_once $config['homedir'].'/include/functions_treeview.php';
-
-        $id = (int) get_parameter('id');
-        $type = (string) get_parameter('type');
-
-        $server = [];
-        if (is_metaconsole()) {
-            $server_id = (int) get_parameter('serverID');
-            $server = metaconsole_get_servers($server_id);
-        }
-
-        ob_clean();
-
-        echo '<div class="left_align">';
-        if (!empty($id) && !empty($type)) {
-            switch ($type) {
-                case 'agent':
-                    treeview_printTable($id, $server, true);
-                break;
-
-                case 'module':
-                    treeview_printModuleTable($id, $server, true);
-                break;
-
-                case 'alert':
-                    treeview_printAlertsTable($id, $server, true);
-                break;
-
-                default:
-                    // Nothing
-                break;
-            }
-        }
-
-        echo '<br></div>';
-
-        return;
-    }
-
-    return;
+		echo json_encode(array('success' => 1, 'tree' => $tree->getArray()));
+		return;
+	}
+	
+	if ($getDetail) {
+		require_once($config['homedir']."/include/functions_treeview.php");
+		
+		$id = (int) get_parameter('id');
+		$type = (string) get_parameter('type');
+		
+		$server = array();
+		if (is_metaconsole()) {
+			$server_id = (int) get_parameter('serverID');
+			$server = metaconsole_get_servers($server_id);
+		}
+		
+		ob_clean();
+		
+		echo '<div class="left_align">';
+		if (!empty($id) && !empty($type)) {
+			switch ($type) {
+				case 'agent':
+					treeview_printTable($id, $server, true);
+					break;
+				case 'module':
+					treeview_printModuleTable($id, $server, true);
+					break;
+				case 'alert':
+					treeview_printAlertsTable($id, $server, true);
+					break;
+				default:
+					// Nothing
+					break;
+			}
+		}
+		echo '<br></div>';
+				
+		return;
+	}
+	
+	return;
 }
+?>
\ No newline at end of file
diff --git a/pandora_console/include/class/Tree.class.php b/pandora_console/include/class/Tree.class.php
index eda92b48b5..4ad71f9ce1 100644
--- a/pandora_console/include/class/Tree.class.php
+++ b/pandora_console/include/class/Tree.class.php
@@ -1,904 +1,762 @@
 <?php
-// Pandora FMS- http://pandorafms.com
+//Pandora FMS- http://pandorafms.com
 // ==================================================
 // Copyright (c) 2005-2011 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 Lesser General Public License
 // as published by the Free Software Foundation; 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.
-class Tree
-{
 
-    protected $type = null;
+class Tree {
+	protected $type = null;
+	protected $rootType = null;
+	protected $id = -1;
+	protected $rootID = -1;
+	protected $serverID = false;
+	protected $serverName = '';
+	protected $tree = array();
+	protected $filter = array();
+	protected $childrenMethod = "on_demand";
 
-    protected $rootType = null;
+	protected $userGroupsACL;
+	protected $userGroups;
+	protected $userGroupsArray;
 
-    protected $id = -1;
+	protected $access = false;
 
-    protected $rootID = -1;
+	protected $L1fieldName = '';
+	protected $L1fieldNameSql = '';
+	protected $L1extraFields = array();
+	protected $L1inner = '';
+	protected $L1innerInside = '';
+	protected $L1orderByFinal = '';
 
-    protected $serverID = false;
+	protected $L2condition = '';
+	protected $L2conditionInside = '';
+	protected $L2inner = '';
+	protected $avoid_condition = false;
 
-    protected $serverName = '';
+	protected $L3forceTagCondition = false;
 
-    protected $tree = [];
+	const TV_DEFAULT_AGENT_STATUS = -1;
 
-    protected $filter = [];
+	public function __construct($type, $rootType = '', $id = -1, $rootID = -1, $serverID = false, $childrenMethod = "on_demand", $access = 'AR') {
 
-    protected $childrenMethod = 'on_demand';
+		$this->type = $type;
+		$this->rootType = !empty($rootType) ? $rootType : $type;
+		$this->id = $id;
+		$this->rootID = !empty($rootID) ? $rootID : $id;
+		$this->serverID = $serverID;
+		if (is_metaconsole()) {
+			$this->serverName = metaconsole_get_server_by_id($serverID);
+		}
+		$this->childrenMethod = $childrenMethod;
+		$this->access = $access;
 
-    protected $userGroupsACL;
+		$userGroupsACL = users_get_groups(false, $this->access);
 
-    protected $userGroups;
+		$this->userGroupsACL = empty($userGroupsACL) ? false : $userGroupsACL;
+		$this->userGroups = $this->userGroupsACL;
+		$this->userGroupsArray = array_keys($this->userGroups);
 
-    protected $userGroupsArray;
+		global $config;
+		include_once($config['homedir']."/include/functions_servers.php");
+		include_once($config['homedir']."/include/functions_modules.php");
+		require_once($config['homedir']."/include/functions_tags.php");
+		enterprise_include_once("include/functions_agents.php");
 
-    protected $access = false;
+		if (is_metaconsole()) enterprise_include_once("meta/include/functions_ui_meta.php");
+	}
 
-    protected $L1fieldName = '';
+	public function setFilter($filter) {
+		// There is not module filter in metaconsole.
+		if (is_metaconsole()) {
+			$filter['searchModule'] = "";
+			$filter['statusModule'] = self::TV_DEFAULT_AGENT_STATUS;
+		}
+		$this->filter = $filter;
+	}
 
-    protected $L1fieldNameSql = '';
+	protected function getEmptyModuleFilterStatus() {
+		return (
+			!isset($this->filter['statusModule']) ||
+			$this->filter['statusModule'] == -1
+		);
+	}
 
-    protected $L1extraFields = [];
+	protected function getModuleSearchFilter() {
+		if (empty($this->filter['searchModule'])) {
+			return "";
+		}
+		return " AND tam.nombre LIKE '%%".$this->filter['searchModule']."%%' ";
+	}
 
-    protected $L1inner = '';
-
-    protected $L1innerInside = '';
-
-    protected $L1orderByFinal = '';
-
-    protected $L2condition = '';
-
-    protected $L2conditionInside = '';
-
-    protected $L2inner = '';
-
-    protected $L3forceTagCondition = false;
-
-    const TV_DEFAULT_AGENT_STATUS = -1;
+	protected function getAgentSearchFilter() {
+		if (empty($this->filter['searchAgent'])) return "";
+		return " AND LOWER(ta.alias) LIKE LOWER('%%".$this->filter['searchAgent']."%%')";
+	}
 
 
-    public function __construct($type, $rootType='', $id=-1, $rootID=-1, $serverID=false, $childrenMethod='on_demand', $access='AR')
-    {
-        $this->type = $type;
-        $this->rootType = !empty($rootType) ? $rootType : $type;
-        $this->id = $id;
-        $this->rootID = !empty($rootID) ? $rootID : $id;
-        $this->serverID = $serverID;
-        if (is_metaconsole()) {
-            $this->serverName = metaconsole_get_server_by_id($serverID);
-        }
+	protected function getAgentStatusFilter ($status = self::TV_DEFAULT_AGENT_STATUS) {
+		if ($status == self::TV_DEFAULT_AGENT_STATUS)
+			$status = $this->filter['statusAgent'];
 
-        $this->childrenMethod = $childrenMethod;
-        $this->access = $access;
-
-        $userGroupsACL = users_get_groups(false, $this->access);
-        $this->userGroupsACL = empty($userGroupsACL) ? false : $userGroupsACL;
-        $this->userGroups = $this->userGroupsACL;
-        $this->userGroupsArray = array_keys($this->userGroups);
-
-        global $config;
-        include_once $config['homedir'].'/include/functions_servers.php';
-        include_once $config['homedir'].'/include/functions_modules.php';
-        include_once $config['homedir'].'/include/functions_tags.php';
-        enterprise_include_once('include/functions_agents.php');
-
-        if (is_metaconsole()) {
-            enterprise_include_once('meta/include/functions_ui_meta.php');
-        }
-    }
-
-
-    public function setFilter($filter)
-    {
-        // There is not module filter in metaconsole.
-        if (is_metaconsole()) {
-            $filter['searchModule'] = '';
-            $filter['statusModule'] = self::TV_DEFAULT_AGENT_STATUS;
-        }
-
-        $this->filter = $filter;
-    }
-
-
-    protected function getEmptyModuleFilterStatus()
-    {
-        return (
-            !isset($this->filter['statusModule']) ||
-            $this->filter['statusModule'] == -1
-        );
-    }
-
-
-    protected function getModuleSearchFilter()
-    {
-        if (empty($this->filter['searchModule'])) {
-            return '';
-        }
-
-        return " AND tam.nombre LIKE '%%".$this->filter['searchModule']."%%' ";
-    }
-
-
-    protected function getAgentSearchFilter()
-    {
-        if (empty($this->filter['searchAgent'])) {
-            return '';
-        }
-
-        return " AND LOWER(ta.alias) LIKE LOWER('%%".$this->filter['searchAgent']."%%')";
-    }
-
-
-    protected function getAgentStatusFilter($status=self::TV_DEFAULT_AGENT_STATUS)
-    {
-        if ($status == self::TV_DEFAULT_AGENT_STATUS) {
-            $status = $this->filter['statusAgent'];
-        }
-
-        $agent_status_filter = '';
-        switch ($status) {
-            case AGENT_STATUS_ALL:
-            break;
-
-            case AGENT_STATUS_NOT_INIT:
-                $agent_status_filter = ' AND (ta.total_count = 0
-											OR ta.total_count = ta.notinit_count) ';
-            break;
-
-            case AGENT_STATUS_CRITICAL:
-                $agent_status_filter = ' AND ta.critical_count > 0 ';
-            break;
-
-            case AGENT_STATUS_WARNING:
-                $agent_status_filter = ' AND (ta.critical_count = 0
-											AND ta.warning_count > 0) ';
-            break;
-
-            case AGENT_STATUS_UNKNOWN:
-                $agent_status_filter = ' AND (ta.critical_count = 0
+		$agent_status_filter = "";
+		switch ($status) {
+			case AGENT_STATUS_ALL:
+				break;
+			case AGENT_STATUS_NOT_INIT:
+				$agent_status_filter = " AND (ta.total_count = 0
+											OR ta.total_count = ta.notinit_count) ";
+				break;
+			case AGENT_STATUS_CRITICAL:
+				$agent_status_filter = " AND ta.critical_count > 0 ";
+				break;
+			case AGENT_STATUS_WARNING:
+				$agent_status_filter = " AND (ta.critical_count = 0
+											AND ta.warning_count > 0) ";
+				break;
+			case AGENT_STATUS_UNKNOWN:
+				$agent_status_filter = " AND (ta.critical_count = 0
 											AND ta.warning_count = 0
-											AND ta.unknown_count > 0) ';
-            break;
-
-            case AGENT_STATUS_NORMAL:
-                $agent_status_filter = ' AND (ta.critical_count = 0
+											AND ta.unknown_count > 0) ";
+				break;
+			case AGENT_STATUS_NORMAL:
+				$agent_status_filter = " AND (ta.critical_count = 0
 											AND ta.warning_count = 0
 											AND ta.unknown_count = 0
-											AND ta.normal_count > 0) ';
-            break;
-        }
+											AND ta.normal_count > 0) ";
+				break;
+		}
 
-        return $agent_status_filter;
-    }
+		return $agent_status_filter;
+	}
 
+	protected function getFirstLevelFields() {
+		$fields = array (
+			"g AS " . $this->L1fieldName,
+			"SUM(x_critical) AS total_critical_count",
+			"SUM(x_warning) AS total_warning_count",
+			"SUM(x_normal) AS total_normal_count",
+			"SUM(x_unknown) AS total_unknown_count",
+			"SUM(x_not_init) AS total_not_init_count",
+			"SUM(x_alerts) AS total_alerts_count",
+			"SUM(x_total) AS total_count"
+		);
+		return implode(",", array_merge($fields, $this->L1extraFields));
+	}
 
-    protected function getFirstLevelFields()
-    {
-        $fields = [
-            'g AS '.$this->L1fieldName,
-            'SUM(x_critical) AS total_critical_count',
-            'SUM(x_warning) AS total_warning_count',
-            'SUM(x_normal) AS total_normal_count',
-            'SUM(x_unknown) AS total_unknown_count',
-            'SUM(x_not_init) AS total_not_init_count',
-            'SUM(x_alerts) AS total_alerts_count',
-            'SUM(x_total) AS total_count',
-        ];
-        return implode(',', array_merge($fields, $this->L1extraFields));
-    }
+	protected function getFirstLevelFieldsInside() {
+		return array(
+			'warning' => array(
+				'header' => "0 AS x_critical, SUM(total) AS x_warning, 0 AS x_normal, 0 AS x_unknown, 0 AS x_not_init, 0 AS x_alerts, 0 AS x_total, g",
+				'condition' => "AND " . agents_get_status_clause(AGENT_STATUS_WARNING, $this->filter['show_not_init_agents'])
+			),
+			'critical' => array(
+				'header' => "SUM(total) AS x_critical, 0 AS x_warning, 0 AS x_normal, 0 AS x_unknown, 0 AS x_not_init, 0 AS x_alerts, 0 AS x_total, g",
+				'condition' => "AND " . agents_get_status_clause(AGENT_STATUS_CRITICAL, $this->filter['show_not_init_agents'])
+			),
+			'normal' => array(
+				'header' => "0 AS x_critical, 0 AS x_warning, SUM(total) AS x_normal, 0 AS x_unknown, 0 AS x_not_init, 0 AS x_alerts, 0 AS x_total, g",
+				'condition' => "AND " . agents_get_status_clause(AGENT_STATUS_NORMAL, $this->filter['show_not_init_agents'])
+			),
+			'unknown' => array(
+				'header' => "0 AS x_critical, 0 AS x_warning, 0 AS x_normal, SUM(total) AS x_unknown, 0 AS x_not_init, 0 AS x_alerts, 0 AS x_total, g",
+				'condition' => "AND " . agents_get_status_clause(AGENT_STATUS_UNKNOWN, $this->filter['show_not_init_agents'])
+			),
+			'not_init' => array(
+				'header' => "0 AS x_critical, 0 AS x_warning, 0 AS x_normal, 0 AS x_unknown, SUM(total) AS x_not_init, 0 AS x_alerts, 0 AS x_total, g",
+				'condition' => "AND " . agents_get_status_clause(AGENT_STATUS_NOT_INIT, $this->filter['show_not_init_agents'])
+			),
+			'alerts' => array(
+				'header' => "0 AS x_critical, 0 AS x_warning, 0 AS x_normal, 0 AS x_unknown, 0 AS x_not_init, SUM(total) AS x_alerts, 0 AS x_total, g",
+				'condition' => "AND ta.fired_count > 0"
+			),
+			'total' => array(
+				'header' => "0 AS x_critical, 0 AS x_warning, 0 AS x_normal, 0 AS x_unknown, 0 AS x_not_init, 0 AS x_alerts, SUM(total) AS x_total, g",
+				'condition' => "AND " . agents_get_status_clause(AGENT_STATUS_ALL, $this->filter['show_not_init_agents'])
+			)
+		);
+	}
 
+	protected function getInnerOrLeftJoin () {
+		return $this->filter['show_not_init_agents']
+			? "LEFT"
+			: "INNER";
+	}
 
-    protected function getFirstLevelFieldsInside()
-    {
-        return [
-            'warning'  => [
-                'header'    => '0 AS x_critical, SUM(total) AS x_warning, 0 AS x_normal, 0 AS x_unknown, 0 AS x_not_init, 0 AS x_alerts, 0 AS x_total, g',
-                'condition' => 'AND '.agents_get_status_clause(AGENT_STATUS_WARNING, $this->filter['show_not_init_agents']),
-            ],
-            'critical' => [
-                'header'    => 'SUM(total) AS x_critical, 0 AS x_warning, 0 AS x_normal, 0 AS x_unknown, 0 AS x_not_init, 0 AS x_alerts, 0 AS x_total, g',
-                'condition' => 'AND '.agents_get_status_clause(AGENT_STATUS_CRITICAL, $this->filter['show_not_init_agents']),
-            ],
-            'normal'   => [
-                'header'    => '0 AS x_critical, 0 AS x_warning, SUM(total) AS x_normal, 0 AS x_unknown, 0 AS x_not_init, 0 AS x_alerts, 0 AS x_total, g',
-                'condition' => 'AND '.agents_get_status_clause(AGENT_STATUS_NORMAL, $this->filter['show_not_init_agents']),
-            ],
-            'unknown'  => [
-                'header'    => '0 AS x_critical, 0 AS x_warning, 0 AS x_normal, SUM(total) AS x_unknown, 0 AS x_not_init, 0 AS x_alerts, 0 AS x_total, g',
-                'condition' => 'AND '.agents_get_status_clause(AGENT_STATUS_UNKNOWN, $this->filter['show_not_init_agents']),
-            ],
-            'not_init' => [
-                'header'    => '0 AS x_critical, 0 AS x_warning, 0 AS x_normal, 0 AS x_unknown, SUM(total) AS x_not_init, 0 AS x_alerts, 0 AS x_total, g',
-                'condition' => 'AND '.agents_get_status_clause(AGENT_STATUS_NOT_INIT, $this->filter['show_not_init_agents']),
-            ],
-            'alerts'   => [
-                'header'    => '0 AS x_critical, 0 AS x_warning, 0 AS x_normal, 0 AS x_unknown, 0 AS x_not_init, SUM(total) AS x_alerts, 0 AS x_total, g',
-                'condition' => 'AND ta.fired_count > 0',
-            ],
-            'total'    => [
-                'header'    => '0 AS x_critical, 0 AS x_warning, 0 AS x_normal, 0 AS x_unknown, 0 AS x_not_init, 0 AS x_alerts, SUM(total) AS x_total, g',
-                'condition' => 'AND '.agents_get_status_clause(AGENT_STATUS_ALL, $this->filter['show_not_init_agents']),
-            ],
-        ];
-    }
+	protected function getModuleStatusFilter () {
+		$show_init_condition = ($this->filter['show_not_init_agents'])
+			? ""
+			: " AND ta.notinit_count <> ta.total_count";
 
+		if ($this->getEmptyModuleFilterStatus()) {
+			return $show_init_condition;
+		}
 
-    protected function getInnerOrLeftJoin()
-    {
-        return $this->filter['show_not_init_agents'] ? 'LEFT' : 'INNER';
-    }
+		$field_filter = modules_get_counter_by_states($this->filter['statusModule']);
+		if ($field_filter === false) return " AND 1=0";
 
+		return "AND ta.$field_filter > 0" . $show_init_condition;
+	}
 
-    protected function getModuleStatusFilter()
-    {
-        $show_init_condition = ($this->filter['show_not_init_agents']) ? '' : ' AND ta.notinit_count <> ta.total_count';
-
-        if ($this->getEmptyModuleFilterStatus()) {
-            return $show_init_condition;
-        }
-
-        $field_filter = modules_get_counter_by_states($this->filter['statusModule']);
-        if ($field_filter === false) {
-            return ' AND 1=0';
-        }
-
-        return "AND ta.$field_filter > 0".$show_init_condition;
-    }
-
-
-    protected function getTagJoin()
-    {
-        return 'INNER JOIN ttag_module ttm
+	protected function getTagJoin () {
+		return 'INNER JOIN ttag_module ttm
 			ON tam.id_agente_modulo = ttm.id_agente_modulo';
-    }
+	}
 
+	protected function getTagCondition () {
+		$tags = tags_get_user_applied_agent_tags($this->id, "AR");
+		// All tags permision, returns no condition
+		if ($tags === true) return "";
+		// No permision, do not show anything
+		if ($tags === false) return " AND 1=0";
+		$tags_sql = implode(',', $tags);
+		return "AND ttm.id_tag IN ($tags_sql)";;
+	}
 
-    protected function getTagCondition()
-    {
-        $tags = tags_get_user_applied_agent_tags($this->id, 'AR');
-        // All tags permision, returns no condition
-        if ($tags === true) {
-            return '';
-        }
+	protected function getModuleStatusFilterFromTestado ($state = false, $without_ands = false) {
+		$selected_status = ($state !== false && $state !== self::TV_DEFAULT_AGENT_STATUS)
+			? $state
+			: $this->filter['statusModule'];
 
-        // No permision, do not show anything
-        if ($tags === false) {
-            return ' AND 1=0';
-        }
+		$filter = array(
+			modules_get_state_condition($selected_status)
+		);
+		if (!$this->filter['show_not_init_modules'] && $state === false) {
+			if (!empty($filter))
+			$filter[] = "(
+				tae.estado <> ".AGENT_MODULE_STATUS_NO_DATA."
+				AND tae.estado <> ".AGENT_MODULE_STATUS_NOT_INIT."
+			)";
+		}
+		$filter = implode(" AND ", $filter);
+		return ($without_ands)
+			? $filter
+			: " AND $filter ";
+	}
 
-        $tags_sql = implode(',', $tags);
-        return "AND ttm.id_tag IN ($tags_sql)";
-        ;
-    }
+	public function getGroupAclCondition() {
+		if (users_can_manage_group_all("AR"))  return "";
 
-
-    protected function getModuleStatusFilterFromTestado($state=false, $without_ands=false)
-    {
-        $selected_status = ($state !== false && $state !== self::TV_DEFAULT_AGENT_STATUS) ? $state : $this->filter['statusModule'];
-
-        $filter = [modules_get_state_condition($selected_status)];
-        if (!$this->filter['show_not_init_modules'] && $state === false) {
-            if (!empty($filter)) {
-                $filter[] = '(
-				tae.estado <> '.AGENT_MODULE_STATUS_NO_DATA.'
-				AND tae.estado <> '.AGENT_MODULE_STATUS_NOT_INIT.'
-			)';
-            }
-        }
-
-        $filter = implode(' AND ', $filter);
-        return ($without_ands) ? $filter : " AND $filter ";
-    }
-
-
-    public function getGroupAclCondition()
-    {
-        if (users_can_manage_group_all('AR')) {
-            return '';
-        }
-
-        $groups_str = implode(',', $this->userGroupsArray);
-        return " AND (
+		$groups_str= implode(",", $this->userGroupsArray);
+		return " AND (
 			ta.id_grupo IN ($groups_str)
 			OR tasg.id_group IN ($groups_str)
 		)";
-    }
+	}
 
-
-    protected function getGroupSearchInner()
-    {
-        if (empty($this->filter['searchGroup'])) {
-            return '';
-        }
-
-        return 'INNER JOIN tgrupo tg
+	protected function getGroupSearchInner() {
+		if (empty($this->filter['searchGroup'])) return "";
+		return "INNER JOIN tgrupo tg
 			ON ta.id_grupo = tg.id_grupo
-			OR tasg.id_group = tg.id_grupo';
-    }
-
-
-    protected function getGroupSearchFilter()
-    {
-        if (empty($this->filter['searchGroup'])) {
-            return '';
-        }
-
-        return " AND tg.nombre LIKE '%%".$this->filter['searchGroup']."%%'";
-    }
-
-
-    static function cmpSortNames($a, $b)
-    {
-        return strcmp($a['name'], $b['name']);
-    }
-
-
-    protected function getProcessedItem($item, $server=false)
-    {
-        if (isset($processed_item['is_processed']) && $processed_item['is_processed']) {
-            return $item;
-        }
-
-        $processed_item = [];
-        $processed_item['id'] = $item['id'];
-        $processed_item['name'] = $item['name'];
-        $processed_item['rootID'] = $item['id'];
-        $processed_item['rootType'] = $this->rootType;
-        $processed_item['searchChildren'] = 1;
-
-        if (isset($item['type'])) {
-            $processed_item['type'] = $item['type'];
-        } else {
-            $processed_item['type'] = $this->type;
-        }
-
-        if (isset($item['rootType'])) {
-            $processed_item['rootType'] = $item['rootType'];
-        } else {
-            $processed_item['rootType'] = $this->rootType;
-        }
-
-        if ($processed_item['type'] == 'group') {
-            $processed_item['parent'] = $item['parent'];
-
-            $processed_item['icon'] = empty($item['icon']) ? 'without_group.png' : $item['icon'].'.png';
-        }
-
-        if (isset($item['iconHTML'])) {
-            $processed_item['icon'] = $item['iconHTML'];
-        }
-
-        if (is_metaconsole() && !empty($server)) {
-            $processed_item['serverID'] = $server['id'];
-        }
-
-        $counters = [];
-        if (isset($item['total_unknown_count'])) {
-            $counters['unknown'] = $item['total_unknown_count'];
-        }
-
-        if (isset($item['total_critical_count'])) {
-            $counters['critical'] = $item['total_critical_count'];
-        }
-
-        if (isset($item['total_warning_count'])) {
-            $counters['warning'] = $item['total_warning_count'];
-        }
-
-        if (isset($item['total_not_init_count'])) {
-            $counters['not_init'] = $item['total_not_init_count'];
-        }
-
-        if (isset($item['total_normal_count'])) {
-            $counters['ok'] = $item['total_normal_count'];
-        }
-
-        if (isset($item['total_count'])) {
-            $counters['total'] = $item['total_count'];
-        }
-
-        if (isset($item['total_fired_count'])) {
-            $counters['alerts'] = $item['total_fired_count'];
-        }
-
-        if (!empty($counters)) {
-            $processed_item['counters'] = $counters;
-        }
-
-        if (!empty($processed_item)) {
-            $processed_item['is_processed'] = true;
-        }
-
-        return $processed_item;
-    }
-
-
-    // This function should be used only when retrieving the data of the metaconsole's nodes
-    protected function getMergedItems($items)
-    {
-        // This variable holds the result
-        $mergedItems = [];
-
-        foreach ($items as $key => $item) {
-            // Avoid the deleted items
-            if (!isset($items[$key]) || empty($item)) {
-                continue;
-            }
-
-            // Store the item in a temporary element
-            $resultItem = $item;
-
-            // The 'id' parameter will be stored as 'server_id' => 'id'
-            $resultItem['id'] = [];
-            $resultItem['id'][$item['serverID']] = $item['id'];
-            $resultItem['rootID'] = [];
-            $resultItem['rootID'][$item['serverID']] = $item['rootID'];
-            $resultItem['serverID'] = [];
-            $resultItem['serverID'][$item['serverID']] = $item['rootID'];
-
-            // Initialize counters if any of it don't exist
-            if (!isset($resultItem['counters'])) {
-                $resultItem['counters'] = [];
-            }
-
-            if (!isset($resultItem['counters']['unknown'])) {
-                $resultItem['counters']['unknown'] = 0;
-            }
-
-            if (!isset($resultItem['counters']['critical'])) {
-                $resultItem['counters']['critical'] = 0;
-            }
-
-            if (!isset($resultItem['counters']['warning'])) {
-                $resultItem['counters']['warning'] = 0;
-            }
-
-            if (!isset($resultItem['counters']['not_init'])) {
-                $resultItem['counters']['not_init'] = 0;
-            }
-
-            if (!isset($resultItem['counters']['ok'])) {
-                $resultItem['counters']['ok'] = 0;
-            }
-
-            if (!isset($resultItem['counters']['total'])) {
-                $resultItem['counters']['total'] = 0;
-            }
-
-            if (!isset($resultItem['counters']['alerts'])) {
-                $resultItem['counters']['alerts'] = 0;
-            }
-
-            if ($item['type'] == 'group') {
-                // Add the children
-                if (!isset($resultItem['children'])) {
-                    $resultItem['children'] = [];
-                }
-            }
-
-            // Iterate over the list to search items that match the actual item
-            foreach ($items as $key2 => $item2) {
-                // Skip the actual or empty items
-                if ($key == $key2 || !isset($items[$key2])) {
-                    continue;
-                }
-
-                // Match with the name and type
-                if ($item['name'] == $item2['name'] && $item['type'] == $item2['type']) {
-                    // Add the matched ids
-                    $resultItem['id'][$item2['serverID']] = $item2['id'];
-                    $resultItem['rootID'][$item2['serverID']] = $item2['rootID'];
-                    $resultItem['serverID'][$item2['serverID']] = $item2['rootID'];
-
-                    // Add the matched counters
-                    if (isset($item2['counters']) && !empty($item2['counters'])) {
-                        foreach ($item2['counters'] as $type => $value) {
-                            if (isset($resultItem['counters'][$type])) {
-                                $resultItem['counters'][$type] += $value;
-                            }
-                        }
-                    }
-
-                    if ($item['type'] == 'group') {
-                        // Add the matched children
-                        if (isset($item2['children'])) {
-                            $resultItem['children'] = array_merge($resultItem['children'], $item2['children']);
-                        }
-                    }
-
-                    // Remove the item
-                    unset($items[$key2]);
-                }
-            }
-
-            if ($item['type'] == 'group') {
-                // Get the merged children (recursion)
-                if (!empty($resultItem['children'])) {
-                    $resultItem['children'] = $this->getMergedItems($resultItem['children']);
-                }
-            }
-
-            // Add the resulting item
-            if (!empty($resultItem) && !empty($resultItem['counters']['total'])) {
-                $mergedItems[] = $resultItem;
-            }
-
-            // Remove the item
-            unset($items[$key]);
-        }
-
-        usort($mergedItems, ['Tree', 'cmpSortNames']);
-
-        return $mergedItems;
-    }
-
-
-    protected function processModule(&$module, $server=false, $all_groups)
-    {
-        global $config;
-
-        if (isset($module['children'])) {
-            foreach ($module['children'] as $i => $children) {
-                $this->processModule($module['children'][$i], $server, $all_groups);
-            }
-        }
-
-        $module['type'] = 'module';
-        $module['id'] = (int) $module['id'];
-        $module['name'] = io_safe_output($module['name']);
-        $module['id_module_type'] = (int) $module['id_tipo_modulo'];
-        $module['server_type'] = (int) $module['id_modulo'];
-        $module['status'] = $module['estado'];
-        $module['value'] = $module['datos'];
-
-        if (is_metaconsole()) {
-            $module['serverID'] = $this->serverID;
-            $module['serverName'] = $this->serverName;
-        } else {
-            $module['serverName'] = false;
-            $module['serverID'] = false;
-        }
-
-        if (!isset($module['value'])) {
-            $module['value'] = modules_get_last_value($module['id']);
-        }
-
-        // Status
-        switch ($module['status']) {
-            case AGENT_MODULE_STATUS_CRITICAL_ALERT:
-                $module['alert'] = 1;
-            case AGENT_MODULE_STATUS_CRITICAL_BAD:
-                $statusType = STATUS_MODULE_CRITICAL_BALL;
-                $statusTitle = __('CRITICAL');
-                $module['statusText'] = 'critical';
-            break;
-
-            case AGENT_MODULE_STATUS_WARNING_ALERT:
-                $module['alert'] = 1;
-            case AGENT_MODULE_STATUS_WARNING:
-                $statusType = STATUS_MODULE_WARNING_BALL;
-                $statusTitle = __('WARNING');
-                $module['statusText'] = 'warning';
-            break;
-
-            case AGENT_MODULE_STATUS_UNKNOWN:
-                $statusType = STATUS_MODULE_UNKNOWN_BALL;
-                $statusTitle = __('UNKNOWN');
-                $module['statusText'] = 'unknown';
-            break;
-
-            case AGENT_MODULE_STATUS_NO_DATA:
-            case AGENT_MODULE_STATUS_NOT_INIT:
-                $statusType = STATUS_MODULE_NO_DATA_BALL;
-                $statusTitle = __('NO DATA');
-                $module['statusText'] = 'not_init';
-            break;
-
-            case AGENT_MODULE_STATUS_NORMAL_ALERT:
-                $module['alert'] = 1;
-            case AGENT_MODULE_STATUS_NORMAL:
-            default:
-                $statusType = STATUS_MODULE_OK_BALL;
-                $statusTitle = __('NORMAL');
-                $module['statusText'] = 'ok';
-            break;
-        }
-
-        if ($statusType !== STATUS_MODULE_UNKNOWN_BALL
-            && $statusType !== STATUS_MODULE_NO_DATA_BALL
-        ) {
-            if (is_numeric($module['value'])) {
-                $statusTitle .= ' : '.format_for_graph($module['value']);
-            } else {
-                $statusTitle .= ' : '.substr(io_safe_output($module['value']), 0, 42);
-            }
-        }
-
-        $module['statusImageHTML'] = ui_print_status_image($statusType, $statusTitle, true);
-
-        // HTML of the server type image
-        $module['serverTypeHTML'] = servers_show_type($module['server_type']);
-
-        // Link to the Module graph
-        // ACL
-        $acl_graphs = false;
-        $module['showGraphs'] = 0;
-
-        // Avoid the check on the metaconsole. Too slow to show/hide an icon depending on the permissions
-        if (!empty($group_id) && !is_metaconsole()) {
-            $acl_graphs = check_acl_one_of_groups($config['id_user'], $all_groups, 'RR');
-        } else if (!empty($all_groups)) {
-            $acl_graphs = true;
-        }
-
-        if ($acl_graphs) {
-            $module['showGraphs'] = 1;
-        }
-
-        if ($module['showGraphs']) {
-            $graphType = return_graphtype($module['id_module_type']);
-            $url = ui_get_full_url('operation/agentes/stat_win.php', false, false, false);
-            $winHandle = dechex(crc32($module['id'].$module['name']));
-
-            $graph_params = [
-                'type'    => $graphType,
-                'period'  => SECONDS_1DAY,
-                'id'      => $module['id'],
-                'label'   => base64_encode($module['name']),
-                'refresh' => SECONDS_10MINUTES,
-            ];
-
-            if (is_metaconsole()) {
-                // Set the server id
-                $graph_params['server'] = $module['serverID'];
-            }
-
-            $graph_params_str = http_build_query($graph_params);
-            $moduleGraphURL = "$url?$graph_params_str";
-
-            $module['moduleGraph'] = [
-                'url'    => $moduleGraphURL,
-                'handle' => $winHandle,
-            ];
-
-            // Info to be able to open the snapshot image new page
-            $module['snapshot'] = ui_get_snapshot_link(
-                [
-                    'id_module'   => $module['id'],
-                    'interval'    => $module['current_interval'],
-                    'module_name' => $module['name'],
-                    'id_node'     => $module['serverID'] ? $module['serverID'] : 0,
-                ],
-                true
-            );
-        }
-
-        // Alerts fired image
-        if ((bool) $module['alerts']) {
-            $module['alertsImageHTML'] = html_print_image('images/bell.png', true, ['title' => __('Module alerts')]);
-        }
-    }
-
-
-    protected function processModules(&$modules, $server=false)
-    {
-        if (!empty($modules)) {
-            $all_groups = modules_get_agent_groups($modules[0]['id']);
-        }
-
-        foreach ($modules as $iterator => $module) {
-            $this->processModule($modules[$iterator], $server, $all_groups);
-        }
-    }
-
-
-    protected function processAgent(&$agent, $server=false)
-    {
-        global $config;
-
-        $agent['type'] = 'agent';
-        $agent['id'] = (int) $agent['id'];
-        $agent['name'] = $agent['name'];
-
-        $agent['rootID'] = $this->rootID;
-        $agent['rootType'] = $this->rootType;
-
-        if (is_metaconsole()) {
-            if (isset($agent['server_id'])) {
-                $agent['serverID'] = $agent['server_id'];
-            } else if (!empty($server)) {
-                $agent['serverID'] = $server['id'];
-            }
-        }
-
-        // Counters
-        if (empty($agent['counters'])) {
-            $agent['counters'] = [];
-
-            $agent['counters']['unknown'] = isset($agent['unknown_count']) ? $agent['unknown_count'] : 0;
-            $agent['counters']['critical'] = isset($agent['critical_count']) ? $agent['critical_count'] : 0;
-            $agent['counters']['warning'] = isset($agent['warning_count']) ? $agent['warning_count'] : 0;
-            $agent['counters']['not_init'] = isset($agent['notinit_count']) ? $agent['notinit_count'] : 0;
-            $agent['counters']['ok'] = isset($agent['normal_count']) ? $agent['normal_count'] : 0;
-            $agent['counters']['total'] = isset($agent['total_count']) ? $agent['total_count'] : 0;
-            $agent['counters']['alerts'] = isset($agent['fired_count']) ? $agent['fired_count'] : 0;
-        }
-
-        // Status image
-        $agent['statusImageHTML'] = agents_tree_view_status_img_ball(
-            $agent['counters']['critical'],
-            $agent['counters']['warning'],
-            $agent['counters']['unknown'],
-            $agent['counters']['total'],
-            $agent['counters']['not_init']
-        );
-
-        // Alerts fired image
-        $agent['alertImageHTML'] = agents_tree_view_alert_img_ball($agent['counters']['alerts']);
-
-        // search module recalculate counters
-        if (array_key_exists('state_normal', $agent)) {
-            $agent['counters']['unknown'] = $agent['state_unknown'];
-            $agent['counters']['critical'] = $agent['state_critical'];
-            $agent['counters']['warning'] = $agent['state_warning'];
-            $agent['counters']['not_init'] = $agent['state_notinit'];
-            $agent['counters']['ok'] = $agent['state_normal'];
-            $agent['counters']['total'] = $agent['state_total'];
-
-            $agent['critical_count'] = $agent['counters']['critical'];
-            $agent['warning_count'] = $agent['counters']['warning'];
-            $agent['unknown_count'] = $agent['counters']['unknown'];
-            $agent['notinit_count'] = $agent['counters']['not_init'];
-            $agent['normal_count'] = $agent['counters']['ok'];
-            $agent['total_count'] = $agent['counters']['total'];
-        }
-
-        if (!$this->getEmptyModuleFilterStatus()) {
-            $agent['counters']['unknown'] = 0;
-            $agent['counters']['critical'] = 0;
-            $agent['counters']['warning'] = 0;
-            $agent['counters']['not_init'] = 0;
-            $agent['counters']['ok'] = 0;
-            $agent['counters']['total'] = 0;
-            switch ($this->filter['statusModule']) {
-                case AGENT_MODULE_STATUS_CRITICAL_ALERT:
-                case AGENT_MODULE_STATUS_CRITICAL_BAD:
-                    $agent['counters']['critical'] = $agent['critical_count'];
-                    $agent['counters']['total'] = $agent['critical_count'];
-                break;
-
-                case AGENT_MODULE_STATUS_WARNING_ALERT:
-                case AGENT_MODULE_STATUS_WARNING:
-                    $agent['counters']['warning'] = $agent['warning_count'];
-                    $agent['counters']['total'] = $agent['warning_count'];
-                break;
-
-                case AGENT_MODULE_STATUS_UNKNOWN:
-                    $agent['counters']['unknown'] = $agent['unknown_count'];
-                    $agent['counters']['total'] = $agent['unknown_count'];
-                break;
-
-                case AGENT_MODULE_STATUS_NO_DATA:
-                case AGENT_MODULE_STATUS_NOT_INIT:
-                    $agent['counters']['not_init'] = $agent['notinit_count'];
-                    $agent['counters']['total'] = $agent['notinit_count'];
-                break;
-
-                case AGENT_MODULE_STATUS_NORMAL_ALERT:
-                case AGENT_MODULE_STATUS_NORMAL:
-                    $agent['counters']['ok'] = $agent['normal_count'];
-                    $agent['counters']['total'] = $agent['normal_count'];
-                break;
-            }
-        }
-
-        if (!$this->filter['show_not_init_modules']) {
-            $agent['counters']['total'] -= $agent['counters']['not_init'];
-            $agent['counters']['not_init'] = 0;
-        }
-
-        // Quiet image
-        if (isset($agent['quiet']) && $agent['quiet']) {
-            $agent['quietImageHTML'] = html_print_image('/images/dot_blue.png', true, ['title' => __('Quiet')]);
-        }
-
-        // Children
-        if (empty($agent['children'])) {
-            $agent['children'] = [];
-            if ($agent['counters']['total'] > 0) {
-                switch ($this->childrenMethod) {
-                    case 'on_demand':
-                        $agent['searchChildren'] = 1;
-                    break;
-
-                    case 'live':
-                        $agent['searchChildren'] = 0;
-                    break;
-                }
-            } else {
-                switch ($this->childrenMethod) {
-                    case 'on_demand':
-                        $agent['searchChildren'] = 0;
-                    break;
-
-                    case 'live':
-                        $agent['searchChildren'] = 0;
-                    break;
-                }
-            }
-        }
-    }
-
-
-    protected function processAgents(&$agents, $server=false)
-    {
-        if (!empty($agents)) {
-            foreach ($agents as $iterator => $agent) {
-                $this->processAgent($agents[$iterator], $server);
-            }
-        }
-    }
-
-
-    protected function getData()
-    {
-
-    }
-
-
-    protected function getFirstLevel()
-    {
-        $sql = $this->getFirstLevelSql();
-        $items = db_get_all_rows_sql($sql);
-        if ($items === false) {
-            $items = [];
-        }
-
-        $this->tree = $this->getProcessedItemsFirstLevel($items);
-    }
-
-
-    protected function getProcessedItemsFirstLevel($items)
-    {
-        $processed_items = [];
-        foreach ($items as $key => $item) {
-            $processed_item = $this->getProcessedItem($item);
-            $processed_items[] = $processed_item;
-        }
-
-        return $processed_items;
-    }
-
-
-    protected function getFirstLevelSql()
-    {
-        $fields = $this->getFirstLevelFields();
-        $field_name_sql = $this->L1fieldNameSql;
-        $inside_fields = $this->getFirstLevelFieldsInside();
-        $inner = $this->L1inner;
-        $inner_inside = $this->L1innerInside;
-        $order_by_final = $this->L1orderByFinal;
-
-        $group_inner = $this->getGroupSearchInner();
-        $group_acl = $this->getGroupAclCondition();
-        $group_search_filter = $this->getGroupSearchFilter();
-        $agent_search_filter = $this->getAgentSearchFilter();
-        $agent_status_filter = $this->getAgentStatusFilter();
-        $module_search_filter = $this->getModuleSearchFilter();
-        $module_status_inner = '';
-        $module_status_filter = $this->getModuleStatusFilterFromTestado();
-        if (!empty($module_status_filter)) {
-            $module_status_inner = '
+			OR tasg.id_group = tg.id_grupo"
+		;
+	}
+
+	protected function getGroupSearchFilter() {
+		if (empty($this->filter['searchGroup'])) return "";
+		return " AND tg.nombre LIKE '%%" . $this->filter['searchGroup'] . "%%'";
+	}
+
+	static function cmpSortNames($a, $b) {
+		return strcmp($a["name"], $b["name"]);
+	}
+
+	protected function getProcessedItem ($item, $server = false) {
+
+		if (isset($processed_item['is_processed']) && $processed_item['is_processed'])
+			return $item;
+
+		$processed_item = array();
+		$processed_item['id'] = $item['id'];
+		$processed_item['name'] = $item['name'];
+		$processed_item['rootID'] = $item['id'];
+		$processed_item['rootType'] = $this->rootType;
+		$processed_item['searchChildren'] = 1;
+
+		if (isset($item['type']))
+			$processed_item['type'] = $item['type'];
+		else
+			$processed_item['type'] = $this->type;
+
+		if (isset($item['rootType']))
+			$processed_item['rootType'] = $item['rootType'];
+		else
+			$processed_item['rootType'] = $this->rootType;
+
+		if ($processed_item['type'] == 'group') {
+			$processed_item['parent'] = $item['parent'];
+
+			$processed_item['icon'] = empty($item['icon'])
+				? "without_group.png"
+				: $item['icon'].".png";
+		}
+		if (isset($item['iconHTML'])) {
+			$processed_item['icon'] = $item['iconHTML'];
+		}
+
+		if (is_metaconsole() && !empty($server)) {
+			$processed_item['serverID'] = $server['id'];
+		}
+
+		$counters = array();
+		if (isset($item['total_unknown_count']))
+			$counters['unknown'] = $item['total_unknown_count'];
+		if (isset($item['total_critical_count']))
+			$counters['critical'] = $item['total_critical_count'];
+		if (isset($item['total_warning_count']))
+			$counters['warning'] = $item['total_warning_count'];
+		if (isset($item['total_not_init_count']))
+			$counters['not_init'] = $item['total_not_init_count'];
+		if (isset($item['total_normal_count']))
+			$counters['ok'] = $item['total_normal_count'];
+		if (isset($item['total_count']))
+			$counters['total'] = $item['total_count'];
+		if (isset($item['total_fired_count']))
+			$counters['alerts'] = $item['total_fired_count'];
+
+		if (!empty($counters))
+			$processed_item['counters'] = $counters;
+
+		if (!empty($processed_item))
+			$processed_item['is_processed'] = true;
+
+		return $processed_item;
+	}
+
+	// This function should be used only when retrieving the data of the metaconsole's nodes
+	protected function getMergedItems ($items) {
+		// This variable holds the result
+		$mergedItems = array();
+
+		foreach ($items as $key => $item) {
+			// Avoid the deleted items
+			if (!isset($items[$key]) || empty($item))
+				continue;
+
+			// Store the item in a temporary element
+			$resultItem = $item;
+
+			// The 'id' parameter will be stored as 'server_id' => 'id'
+			$resultItem['id'] = array();
+			$resultItem['id'][$item['serverID']] = $item['id'];
+			$resultItem['rootID'] = array();
+			$resultItem['rootID'][$item['serverID']] = $item['rootID'];
+			$resultItem['serverID'] = array();
+			$resultItem['serverID'][$item['serverID']] = $item['rootID'];
+
+			// Initialize counters if any of it don't exist
+			if (!isset($resultItem['counters']))
+				$resultItem['counters'] = array();
+			if (!isset($resultItem['counters']['unknown']))
+				$resultItem['counters']['unknown'] = 0;
+			if (!isset($resultItem['counters']['critical']))
+				$resultItem['counters']['critical'] = 0;
+			if (!isset($resultItem['counters']['warning']))
+				$resultItem['counters']['warning'] = 0;
+			if (!isset($resultItem['counters']['not_init']))
+				$resultItem['counters']['not_init'] = 0;
+			if (!isset($resultItem['counters']['ok']))
+				$resultItem['counters']['ok'] = 0;
+			if (!isset($resultItem['counters']['total']))
+				$resultItem['counters']['total'] = 0;
+			if (!isset($resultItem['counters']['alerts']))
+				$resultItem['counters']['alerts'] = 0;
+
+			if ($item['type'] == 'group') {
+				// Add the children
+				if (!isset($resultItem['children']))
+					$resultItem['children'] = array();
+			}
+
+			// Iterate over the list to search items that match the actual item
+			foreach ($items as $key2 => $item2) {
+				// Skip the actual or empty items
+				if ($key == $key2 || !isset($items[$key2]))
+					continue;
+
+				// Match with the name and type
+				if ($item['name'] == $item2['name'] && $item['type'] == $item2['type']) {
+					// Add the matched ids
+					$resultItem['id'][$item2['serverID']] = $item2['id'];
+					$resultItem['rootID'][$item2['serverID']] = $item2['rootID'];
+					$resultItem['serverID'][$item2['serverID']] = $item2['rootID'];
+
+					// Add the matched counters
+					if (isset($item2['counters']) && !empty($item2['counters'])) {
+						foreach ($item2['counters'] as $type => $value) {
+							if (isset($resultItem['counters'][$type]))
+								$resultItem['counters'][$type] += $value;
+						}
+					}
+
+					if ($item['type'] == 'group') {
+						// Add the matched children
+						if (isset($item2['children']))
+							$resultItem['children'] = array_merge($resultItem['children'], $item2['children']);
+					}
+
+					// Remove the item
+					unset($items[$key2]);
+				}
+			}
+
+			if ($item['type'] == 'group') {
+				// Get the merged children (recursion)
+				if (!empty($resultItem['children']))
+					$resultItem['children'] = $this->getMergedItems($resultItem['children']);
+
+			}
+
+			// Add the resulting item
+			if (!empty($resultItem) && !empty($resultItem['counters']['total']))
+				$mergedItems[] = $resultItem;
+
+			// Remove the item
+			unset($items[$key]);
+		}
+
+		usort($mergedItems, array("Tree", "cmpSortNames"));
+
+		return $mergedItems;
+	}
+
+	protected function processModule (&$module, $server = false, $all_groups) {
+		global $config;
+		
+		if (isset($module['children'])) {
+			foreach ($module['children'] as $i => $children) {
+				$this->processModule($module['children'][$i], $server, $all_groups);
+			}
+		}
+
+		$module['type'] = 'module';
+		$module['id'] = (int) $module['id'];
+		$module['name'] = io_safe_output($module['name']);
+		$module['id_module_type'] = (int) $module['id_tipo_modulo'];
+		$module['server_type'] = (int) $module['id_modulo'];
+		$module['status'] = $module['estado'];
+		$module['value'] = $module['datos'];
+
+		if (is_metaconsole()) {
+			$module['serverID'] = $this->serverID;
+			$module['serverName'] = $this->serverName;
+		}
+		else {
+			$module['serverName'] = false;
+			$module['serverID'] = false;
+		}
+
+		if (!isset($module['value']))
+			$module['value'] = modules_get_last_value($module['id']);
+
+		// Status
+		switch ($module['status']) {
+			case AGENT_MODULE_STATUS_CRITICAL_ALERT:
+				$module['alert'] = 1;
+			case AGENT_MODULE_STATUS_CRITICAL_BAD:
+				$statusType = STATUS_MODULE_CRITICAL_BALL;
+				$statusTitle = __('CRITICAL');
+				$module['statusText'] = "critical";
+				break;
+			case AGENT_MODULE_STATUS_WARNING_ALERT:
+				$module['alert'] = 1;
+			case AGENT_MODULE_STATUS_WARNING:
+				$statusType = STATUS_MODULE_WARNING_BALL;
+				$statusTitle = __('WARNING');
+				$module['statusText'] = "warning";
+				break;
+			case AGENT_MODULE_STATUS_UNKNOWN:
+				$statusType = STATUS_MODULE_UNKNOWN_BALL;
+				$statusTitle = __('UNKNOWN');
+				$module['statusText'] = "unknown";
+				break;
+			case AGENT_MODULE_STATUS_NO_DATA:
+			case AGENT_MODULE_STATUS_NOT_INIT:
+				$statusType = STATUS_MODULE_NO_DATA_BALL;
+				$statusTitle = __('NO DATA');
+				$module['statusText'] = "not_init";
+				break;
+			case AGENT_MODULE_STATUS_NORMAL_ALERT:
+				$module['alert'] = 1;
+			case AGENT_MODULE_STATUS_NORMAL:
+			default:
+				$statusType = STATUS_MODULE_OK_BALL;
+				$statusTitle = __('NORMAL');
+				$module['statusText'] = "ok";
+				break;
+		}
+
+		if ($statusType !== STATUS_MODULE_UNKNOWN_BALL
+				&& $statusType !== STATUS_MODULE_NO_DATA_BALL) {
+			if (is_numeric($module["value"])) {
+				$statusTitle .= " : " . format_for_graph($module["value"]);
+			}
+			else {
+				$statusTitle .= " : " . substr(io_safe_output($module["value"]),0,42);
+			}
+		}
+
+		$module['statusImageHTML'] = ui_print_status_image($statusType, $statusTitle, true);
+
+		// HTML of the server type image
+		$module['serverTypeHTML'] = servers_show_type($module['server_type']);
+
+		// Link to the Module graph
+
+		// ACL
+		$acl_graphs = false;
+		$module["showGraphs"] = 0;
+
+		// Avoid the check on the metaconsole. Too slow to show/hide an icon depending on the permissions
+		if (!empty($group_id) && !is_metaconsole()) {
+			$acl_graphs = check_acl_one_of_groups($config['id_user'], $all_groups, "RR");
+		}
+		else if (!empty($all_groups)) {
+			$acl_graphs = true;
+		}
+
+		if ($acl_graphs) {
+			$module["showGraphs"] = 1;
+		}
+
+		if ($module["showGraphs"]) {
+			$graphType = return_graphtype($module['id_module_type']);
+			$url = ui_get_full_url("operation/agentes/stat_win.php", false, false, false);
+			$winHandle = dechex(crc32($module['id'].$module['name']));
+
+			$graph_params = array(
+					"type" => $graphType,
+					"period" => SECONDS_1DAY,
+					"id" => $module['id'],
+					"label" => base64_encode($module['name']),
+					"refresh" => SECONDS_10MINUTES
+				);
+
+			if (is_metaconsole()) {
+				// Set the server id
+				$graph_params["server"] = $module['serverID'];
+			}
+
+			$graph_params_str = http_build_query($graph_params);
+			$moduleGraphURL = "$url?$graph_params_str";
+
+			$module['moduleGraph'] = array(
+					'url' => $moduleGraphURL,
+					'handle' => $winHandle
+				);
+
+			// Info to be able to open the snapshot image new page
+			$module['snapshot'] = ui_get_snapshot_link(array(
+				'id_module' => $module['id'],
+				'interval' => $module['current_interval'],
+				'module_name' => $module['name'],
+				'id_node' => $module['serverID'] ? $module['serverID'] : 0,
+			), true);
+		}
+
+		// Alerts fired image
+		if ((bool)$module['alerts']) {
+			$module['alertsImageHTML'] = html_print_image("images/bell.png", true, array("title" => __('Module alerts')));
+		}
+	}
+
+	protected function processModules (&$modules, $server = false) {
+		if (!empty($modules)) {
+			$all_groups = modules_get_agent_groups($modules[0]['id']);
+		}
+		foreach ($modules as $iterator => $module) {
+			$this->processModule($modules[$iterator], $server, $all_groups);
+		}
+	}
+
+	protected function processAgent (&$agent, $server = false) {
+		global $config;
+
+		$agent['type'] = 'agent';
+		$agent['id'] = (int) $agent['id'];
+		$agent['name'] = $agent['name'];
+
+		$agent['rootID'] = $this->rootID;
+		$agent['rootType'] = $this->rootType;
+
+		if (is_metaconsole()) {
+			if (isset($agent['server_id']))
+				$agent['serverID'] = $agent['server_id'];
+			else if (!empty($server))
+				$agent['serverID'] = $server['id'];
+		}
+		// Counters
+		if (empty($agent['counters'])) {
+			$agent['counters'] = array();
+
+			$agent['counters']['unknown'] = isset($agent['unknown_count']) ? $agent['unknown_count'] : 0;
+			$agent['counters']['critical'] = isset($agent['critical_count']) ? $agent['critical_count'] : 0;
+			$agent['counters']['warning'] = isset($agent['warning_count']) ? $agent['warning_count'] : 0;
+			$agent['counters']['not_init'] = isset($agent['notinit_count']) ? $agent['notinit_count'] : 0;
+			$agent['counters']['ok'] = isset($agent['normal_count']) ? $agent['normal_count'] : 0;
+			$agent['counters']['total'] = isset($agent['total_count']) ? $agent['total_count'] : 0;
+			$agent['counters']['alerts'] = isset($agent['fired_count']) ? $agent['fired_count'] : 0;
+		}
+
+		// Status image
+		$agent['statusImageHTML'] = agents_tree_view_status_img_ball(
+				$agent['counters']['critical'],
+				$agent['counters']['warning'],
+				$agent['counters']['unknown'],
+				$agent['counters']['total'],
+				$agent['counters']['not_init']);
+
+		// Alerts fired image
+		$agent["alertImageHTML"] = agents_tree_view_alert_img_ball($agent['counters']['alerts']);
+
+		// search module recalculate counters
+		if(array_key_exists('state_normal', $agent)){
+			$agent['counters']['unknown'] = $agent['state_unknown'];
+			$agent['counters']['critical'] = $agent['state_critical'];
+			$agent['counters']['warning'] = $agent['state_warning'];
+			$agent['counters']['not_init'] = $agent['state_notinit'];
+			$agent['counters']['ok'] = $agent['state_normal'];
+			$agent['counters']['total'] = $agent['state_total'];
+
+			$agent['critical_count'] = $agent['counters']['critical'];
+			$agent['warning_count'] = $agent['counters']['warning'];
+			$agent['unknown_count'] = $agent['counters']['unknown'];
+			$agent['notinit_count'] = $agent['counters']['not_init'];
+			$agent['normal_count'] = $agent['counters']['ok'];
+			$agent['total_count'] = $agent['counters']['total'];
+		}
+
+		if (!$this->getEmptyModuleFilterStatus()) {
+			$agent['counters']['unknown'] = 0;
+			$agent['counters']['critical'] = 0;
+			$agent['counters']['warning'] = 0;
+			$agent['counters']['not_init'] = 0;
+			$agent['counters']['ok'] = 0;
+			$agent['counters']['total'] = 0;
+			switch($this->filter['statusModule']) {
+				case AGENT_MODULE_STATUS_CRITICAL_ALERT:
+				case AGENT_MODULE_STATUS_CRITICAL_BAD:
+					$agent['counters']['critical'] = $agent['critical_count'];
+					$agent['counters']['total'] = $agent['critical_count'];
+					break;
+				case AGENT_MODULE_STATUS_WARNING_ALERT:
+				case AGENT_MODULE_STATUS_WARNING:
+					$agent['counters']['warning'] = $agent['warning_count'];
+					$agent['counters']['total'] = $agent['warning_count'];
+					break;
+				case AGENT_MODULE_STATUS_UNKNOWN:
+					$agent['counters']['unknown'] = $agent['unknown_count'];
+					$agent['counters']['total'] = $agent['unknown_count'];
+					break;
+				case AGENT_MODULE_STATUS_NO_DATA:
+				case AGENT_MODULE_STATUS_NOT_INIT:
+					$agent['counters']['not_init'] = $agent['notinit_count'];
+					$agent['counters']['total'] = $agent['notinit_count'];
+					break;
+				case AGENT_MODULE_STATUS_NORMAL_ALERT:
+				case AGENT_MODULE_STATUS_NORMAL:
+					$agent['counters']['ok'] = $agent['normal_count'];
+					$agent['counters']['total'] = $agent['normal_count'];
+					break;
+			}
+		}
+
+		if (!$this->filter['show_not_init_modules']) {
+			$agent['counters']['total'] -= $agent['counters']['not_init'];
+			$agent['counters']['not_init'] = 0;
+		}
+
+		// Quiet image
+		if (isset($agent['quiet']) && $agent['quiet'])
+			$agent['quietImageHTML'] = html_print_image("/images/dot_blue.png", true, array("title" => __('Quiet')));
+
+		// Children
+		if (empty($agent['children'])) {
+			$agent['children'] = array();
+			if ($agent['counters']['total'] > 0) {
+				switch ($this->childrenMethod) {
+					case 'on_demand':
+						$agent['searchChildren'] = 1;
+						break;
+					case 'live':
+						$agent['searchChildren'] = 0;
+						break;
+				}
+			}
+			else {
+				switch ($this->childrenMethod) {
+					case 'on_demand':
+						$agent['searchChildren'] = 0;
+						break;
+					case 'live':
+						$agent['searchChildren'] = 0;
+						break;
+				}
+			}
+		}
+	}
+
+	protected function processAgents (&$agents, $server = false) {
+		if (!empty($agents)) {
+			foreach ($agents as $iterator => $agent) {
+				$this->processAgent($agents[$iterator], $server);
+			}
+		}
+	}
+
+	protected function getData() {
+
+	}
+
+	protected function getFirstLevel() {
+		$sql = $this->getFirstLevelSql();
+		$items = db_get_all_rows_sql($sql);
+		if ($items === false) $items = array();
+
+		$this->tree = $this->getProcessedItemsFirstLevel($items);
+	}
+
+	protected function getProcessedItemsFirstLevel($items){
+		$processed_items = array();
+		foreach ($items as $key => $item) {
+			$processed_item = $this->getProcessedItem($item);
+			$processed_items[] = $processed_item;
+		}
+		return $processed_items;
+	}
+
+	protected function getFirstLevelSql() {
+
+		$fields = $this->getFirstLevelFields();
+		$field_name_sql = $this->L1fieldNameSql;
+		$inside_fields = $this->getFirstLevelFieldsInside();
+		$inner = $this->L1inner;
+		$inner_inside = $this->L1innerInside;
+		$order_by_final = $this->L1orderByFinal;
+
+		$group_inner = $this->getGroupSearchInner();
+		$group_acl = $this->getGroupAclCondition();
+		$group_search_filter = $this->getGroupSearchFilter();
+		$agent_search_filter = $this->getAgentSearchFilter();
+		$agent_status_filter = $this->getAgentStatusFilter();
+		$module_search_filter = $this->getModuleSearchFilter();
+		$module_status_inner = "";
+		$module_status_filter = $this->getModuleStatusFilterFromTestado();
+		if (!empty($module_status_filter)) {
+			$module_status_inner = "
 				INNER JOIN tagente_estado tae
-					ON tae.id_agente_modulo = tam.id_agente_modulo';
-        }
+					ON tae.id_agente_modulo = tam.id_agente_modulo";
+		}
 
-        $sql_model = "SELECT %s FROM
+		$sql_model = "SELECT %s FROM
 			(
 				SELECT COUNT(DISTINCT(ta.id_agente)) AS total, $field_name_sql AS g
 					FROM tagente ta
@@ -920,42 +778,34 @@ class Tree
 						$group_acl
 					GROUP BY $field_name_sql
 			) x GROUP BY g";
-        $sql_array = [];
-        foreach ($inside_fields as $inside_field) {
-            $sql_array[] = sprintf(
-                $sql_model,
-                $inside_field['header'],
-                $inside_field['condition']
-            );
-        }
-
-        $sql = "SELECT $fields FROM (".implode(' UNION ALL ', $sql_array).") x2
+		$sql_array = array();
+		foreach ($inside_fields as $inside_field) {
+			$sql_array[] = sprintf(
+				$sql_model,
+				$inside_field['header'],
+				$inside_field['condition']
+			);
+		}
+		$sql = "SELECT $fields FROM (" . implode(" UNION ALL ", $sql_array) . ") x2
 			$inner
 			GROUP BY g
 			ORDER BY $order_by_final";
-        return $sql;
-    }
+		return $sql;
+	}
 
+	protected function getSecondLevel() {
+		$sql = $this->getSecondLevelSql();
+		$data = db_process_sql($sql);
+		if (empty($data)) {
+			$this->tree = array();
+			return;
+		}
+		$this->processAgents($data);
+		$this->tree = $data;
+	}
 
-    protected function getSecondLevel()
-    {
-        $sql = $this->getSecondLevelSql();
-        $data = db_process_sql($sql);
-        if (empty($data)) {
-            $this->tree = [];
-            return;
-        }
-
-        $this->processAgents($data);
-
-        $this->tree = $data;
-    }
-
-
-    protected function getSecondLevelSql()
-    {
-        $columns = sprintf(
-            'ta.id_agente AS id, ta.nombre AS name, ta.alias,
+	protected function getSecondLevelSql() {
+		$columns = sprintf("ta.id_agente AS id, ta.nombre AS name, ta.alias,
 				ta.fired_count, ta.normal_count, ta.warning_count,
 				ta.critical_count, ta.unknown_count, ta.notinit_count,
 				ta.total_count, ta.quiet,
@@ -965,29 +815,29 @@ class Tree
 				SUM(if(%s, 1, 0)) as state_notinit,
 				SUM(if(%s, 1, 0)) as state_normal,
 				SUM(if(%s AND tae.estado IS NOT NULL, 1, 0)) as state_total
-			',
-            $this->getModuleStatusFilterFromTestado(AGENT_MODULE_STATUS_CRITICAL_ALERT, true),
-            $this->getModuleStatusFilterFromTestado(AGENT_MODULE_STATUS_WARNING_ALERT, true),
-            $this->getModuleStatusFilterFromTestado(AGENT_MODULE_STATUS_UNKNOWN, true),
-            $this->getModuleStatusFilterFromTestado(AGENT_MODULE_STATUS_NO_DATA, true),
-            $this->getModuleStatusFilterFromTestado(AGENT_MODULE_STATUS_NORMAL, true),
-            $this->getModuleStatusFilterFromTestado(self::TV_DEFAULT_AGENT_STATUS, true)
-        );
+			",
+			$this->getModuleStatusFilterFromTestado(AGENT_MODULE_STATUS_CRITICAL_ALERT, true),
+			$this->getModuleStatusFilterFromTestado(AGENT_MODULE_STATUS_WARNING_ALERT, true),
+			$this->getModuleStatusFilterFromTestado(AGENT_MODULE_STATUS_UNKNOWN, true),
+			$this->getModuleStatusFilterFromTestado(AGENT_MODULE_STATUS_NO_DATA, true),
+			$this->getModuleStatusFilterFromTestado(AGENT_MODULE_STATUS_NORMAL, true),
+			$this->getModuleStatusFilterFromTestado(self::TV_DEFAULT_AGENT_STATUS, true)
+		);
 
-        $inner_or_left = $this->getInnerOrLeftJoin();
-        $group_inner = $this->getGroupSearchInner();
-        $group_acl = $this->getGroupAclCondition();
-        $group_search_filter = $this->getGroupSearchFilter();
-        $agent_search_filter = $this->getAgentSearchFilter();
-        $agent_status_filter = $this->getAgentStatusFilter();
-        $module_search_filter = $this->getModuleSearchFilter();
-        $module_status_filter = $this->getModuleStatusFilter();
+		$inner_or_left = $this->getInnerOrLeftJoin();
+		$group_inner = $this->getGroupSearchInner();
+		$group_acl = $this->getGroupAclCondition();
+		$group_search_filter = $this->getGroupSearchFilter();
+		$agent_search_filter = $this->getAgentSearchFilter();
+		$agent_status_filter = $this->getAgentStatusFilter();
+		$module_search_filter = $this->getModuleSearchFilter();
+		$module_status_filter = $this->getModuleStatusFilter();
 
-        $condition = $this->L2condition;
-        $condition_inside = $this->L2conditionInside;
-        $inner = $this->L2inner;
+		$condition = $this->L2condition;
+		$condition_inside = $this->L2conditionInside;
+		$inner = $this->L2inner;
 
-        $sql = "SELECT $columns
+		$sql = "SELECT $columns
 			FROM tagente ta
 			$inner_or_left JOIN tagente_modulo tam
 				ON ta.id_agente = tam.id_agente
@@ -1017,48 +867,49 @@ class Tree
 			ORDER BY ta.alias ASC, ta.id_agente ASC
 		";
 
-        return $sql;
-    }
+		return $sql;
+	}
 
+	protected function getThirdLevel() {
+		$sql = $this->getThirdLevelSql();
+		$data = db_process_sql($sql);
+		if (empty($data)) {
+			$this->tree = array();
+			return;
+		}
+		$data = $this->getProcessedModules($data);
+		$this->processModules($data);
+		$this->tree = $data;
+	}
 
-    protected function getThirdLevel()
-    {
-        $sql = $this->getThirdLevelSql();
-        $data = db_process_sql($sql);
-        if (empty($data)) {
-            $this->tree = [];
-            return;
-        }
+	protected function getThirdLevelSql() {
+		// Get the server id
+		$serverID = $this->serverID;
 
-        $data = $this->getProcessedModules($data);
-        $this->processModules($data);
+		$group_acl = $this->getGroupAclCondition();
+		$agent_search_filter = $this->getAgentSearchFilter();
+		$agent_status_filter = $this->getAgentStatusFilter();
+		$module_search_filter = $this->getModuleSearchFilter();
+		$module_status_filter = $this->getModuleStatusFilterFromTestado();
+		$agent_filter = "AND ta.id_agente = " . $this->id;
+		$tag_condition = $this->getTagCondition();
+		$tag_join = empty($tag_condition) && (!$this->L3forceTagCondition)
+			? ''
+			: $this->getTagJoin();
 
-        $this->tree = $data;
-    }
+		if ($this->avoid_condition === true) {
+			$condition = '';
+			$inner = '';
+		} else {
+			$condition = $this->L2condition;
+			$inner = $this->L2inner;
+		}
 
-
-    protected function getThirdLevelSql()
-    {
-        // Get the server id
-        $serverID = $this->serverID;
-
-        $group_acl = $this->getGroupAclCondition();
-        $agent_search_filter = $this->getAgentSearchFilter();
-        $agent_status_filter = $this->getAgentStatusFilter();
-        $module_search_filter = $this->getModuleSearchFilter();
-        $module_status_filter = $this->getModuleStatusFilterFromTestado();
-        $agent_filter = 'AND ta.id_agente = '.$this->id;
-        $tag_condition = $this->getTagCondition();
-        $tag_join = empty($tag_condition) && (!$this->L3forceTagCondition) ? '' : $this->getTagJoin();
-
-        $condition = $this->L2condition;
-        $inner = $this->L2inner;
-
-        $columns = 'DISTINCT(tam.id_agente_modulo) AS id, tam.nombre AS name,
+		$columns = 'DISTINCT(tam.id_agente_modulo) AS id, tam.nombre AS name,
 			tam.id_tipo_modulo, tam.id_modulo, tae.estado, tae.datos,
 			tam.parent_module_id AS parent, tatm.id AS alerts';
 
-        $sql = "SELECT $columns
+		$sql = "SELECT $columns
 			FROM tagente_modulo tam
 			$tag_join
 			INNER JOIN tagente_estado tae
@@ -1076,81 +927,57 @@ class Tree
 				$group_acl
 				$agent_search_filter
 				$agent_status_filter
-				$module_status_filter
 				$module_search_filter
 				$tag_condition
 			ORDER BY tam.nombre ASC, tam.id_agente_modulo ASC";
-        return $sql;
-    }
 
+		return $sql;
+	}
 
-    public function getJSON()
-    {
-        $this->getData();
+	public function getJSON() {
+		$this->getData();
 
-        return json_encode($this->tree);
-    }
+		return json_encode($this->tree);
+	}
 
+	public function getArray() {
+		$this->getData();
 
-    public function getArray()
-    {
-        $this->getData();
+		return $this->tree;
+	}
 
-        return $this->tree;
-    }
+	static function name2symbol($name) {
+		return str_replace(
+			array(' ','#','/','.','(',')','¿','?','¡','!'),
+			array(
+				'_articapandora_'.ord(' ').'_pandoraartica_',
+				'_articapandora_'.ord('#').'_pandoraartica_',
+				'_articapandora_'.ord('/').'_pandoraartica_',
+				'_articapandora_'.ord('.').'_pandoraartica_',
+				'_articapandora_'.ord('(').'_pandoraartica_',
+				'_articapandora_'.ord(')').'_pandoraartica_',
+				'_articapandora_'.ord('¿').'_pandoraartica_',
+				'_articapandora_'.ord('?').'_pandoraartica_',
+				'_articapandora_'.ord('¡').'_pandoraartica_',
+				'_articapandora_'.ord('!').'_pandoraartica_'
+			),
+			io_safe_output($name)
+		);
+	}
 
+	static function symbol2name($name) {
+		$symbols = ' !"#$%&\'()*+,./:;<=>?@[\\]^{|}~';
+		for ($i = 0; $i < strlen($symbols); $i++) {
+			$name = str_replace('_articapandora_' .
+				ord(substr($symbols, $i, 1)) .'_pandoraartica_',
+				substr($symbols, $i, 1), $name);
+		}
+		return io_safe_input($name);
+	}
 
-    static function name2symbol($name)
-    {
-        return str_replace(
-            [
-                ' ',
-                '#',
-                '/',
-                '.',
-                '(',
-                ')',
-                '¿',
-                '?',
-                '¡',
-                '!',
-            ],
-            [
-                '_articapandora_'.ord(' ').'_pandoraartica_',
-                '_articapandora_'.ord('#').'_pandoraartica_',
-                '_articapandora_'.ord('/').'_pandoraartica_',
-                '_articapandora_'.ord('.').'_pandoraartica_',
-                '_articapandora_'.ord('(').'_pandoraartica_',
-                '_articapandora_'.ord(')').'_pandoraartica_',
-                '_articapandora_'.ord('¿').'_pandoraartica_',
-                '_articapandora_'.ord('?').'_pandoraartica_',
-                '_articapandora_'.ord('¡').'_pandoraartica_',
-                '_articapandora_'.ord('!').'_pandoraartica_',
-            ],
-            io_safe_output($name)
-        );
-    }
-
-
-    static function symbol2name($name)
-    {
-        $symbols = ' !"#$%&\'()*+,./:;<=>?@[\\]^{|}~';
-        for ($i = 0; $i < strlen($symbols); $i++) {
-            $name = str_replace(
-                '_articapandora_'.ord(substr($symbols, $i, 1)).'_pandoraartica_',
-                substr($symbols, $i, 1),
-                $name
-            );
-        }
-
-        return io_safe_input($name);
-    }
-
-
-    protected function getProcessedModules($modules_tree)
-    {
-        return $modules_tree;
-    }
-
+	protected function getProcessedModules($modules_tree) {
+		return $modules_tree;
+	}
 
 }
+?>
diff --git a/pandora_console/include/class/TreeGroup.class.php b/pandora_console/include/class/TreeGroup.class.php
index bef4287c7d..05ba271e24 100644
--- a/pandora_console/include/class/TreeGroup.class.php
+++ b/pandora_console/include/class/TreeGroup.class.php
@@ -36,9 +36,9 @@ class TreeGroup extends Tree
         ];
 
         $this->L2conditionInside = 'AND (
-			ta.id_grupo = '.$this->id.'
-			OR tasg.id_group = '.$this->id.'
-		)';
+            ta.id_grupo = '.$this->id.'
+            OR tasg.id_group = '.$this->id.'
+        )';
     }
 
 
@@ -198,44 +198,44 @@ class TreeGroup extends Tree
         $module_search_filter = '';
         if (!empty($this->filter['searchModule'])) {
             $module_search_inner = '
-				INNER JOIN tagente_modulo tam
-					ON ta.id_agente = tam.id_agente
-				INNER JOIN tagente_estado tae
-					ON tae.id_agente_modulo = tam.id_agente_modulo';
+                INNER JOIN tagente_modulo tam
+                    ON ta.id_agente = tam.id_agente
+                INNER JOIN tagente_estado tae
+                    ON tae.id_agente_modulo = tam.id_agente_modulo';
             $module_search_filter = "AND tam.disabled = 0
-				AND tam.nombre LIKE '%%".$this->filter['searchModule']."%%' ".$this->getModuleStatusFilterFromTestado();
+                AND tam.nombre LIKE '%%".$this->filter['searchModule']."%%' ".$this->getModuleStatusFilterFromTestado();
         }
 
         $table = is_metaconsole() ? 'tmetaconsole_agent' : 'tagente';
         $table_sec = is_metaconsole() ? 'tmetaconsole_agent_secondary_group' : 'tagent_secondary_group';
 
         $sql_model = "SELECT %s FROM
-			(
-				SELECT COUNT(DISTINCT(ta.id_agente)) AS total, id_grupo AS g
-					FROM $table ta
-					$module_search_inner
-					WHERE ta.disabled = 0
-						%s
-						$agent_search_filter
-						$agent_status_filter
-						$module_status_filter
-						$module_search_filter
-						$group_acl
-					GROUP BY id_grupo
-				UNION ALL
-				SELECT COUNT(DISTINCT(ta.id_agente)) AS total, id_group AS g
-					FROM $table ta INNER JOIN $table_sec tasg
-						ON ta.id_agente = tasg.id_agent
-					$module_search_inner
-					WHERE ta.disabled = 0
-						%s
-						$agent_search_filter
-						$agent_status_filter
-						$module_status_filter
-						$module_search_filter
-						$secondary_group_acl
-					GROUP BY id_group
-			) x GROUP BY g";
+            (
+                SELECT COUNT(DISTINCT(ta.id_agente)) AS total, id_grupo AS g
+                    FROM $table ta
+                    $module_search_inner
+                    WHERE ta.disabled = 0
+                        %s
+                        $agent_search_filter
+                        $agent_status_filter
+                        $module_status_filter
+                        $module_search_filter
+                        $group_acl
+                    GROUP BY id_grupo
+                UNION ALL
+                SELECT COUNT(DISTINCT(ta.id_agente)) AS total, id_group AS g
+                    FROM $table ta INNER JOIN $table_sec tasg
+                        ON ta.id_agente = tasg.id_agent
+                    $module_search_inner
+                    WHERE ta.disabled = 0
+                        %s
+                        $agent_search_filter
+                        $agent_status_filter
+                        $module_status_filter
+                        $module_search_filter
+                        $secondary_group_acl
+                    GROUP BY id_group
+            ) x GROUP BY g";
         $sql_array = [];
         foreach ($inside_fields as $inside_field) {
             $sql_array[] = sprintf(
@@ -247,9 +247,9 @@ class TreeGroup extends Tree
         }
 
         $sql = "SELECT $fields FROM (".implode(' UNION ALL ', $sql_array).') x2
-			RIGHT JOIN tgrupo tg
-				ON x2.g = tg.id_grupo
-			GROUP BY tg.id_grupo';
+            RIGHT JOIN tgrupo tg
+                ON x2.g = tg.id_grupo
+            GROUP BY tg.id_grupo';
         $stats = db_get_all_rows_sql($sql);
 
         $group_stats = [];
diff --git a/pandora_console/include/class/TreeService.class.php b/pandora_console/include/class/TreeService.class.php
new file mode 100644
index 0000000000..b55643219d
--- /dev/null
+++ b/pandora_console/include/class/TreeService.class.php
@@ -0,0 +1,334 @@
+<?php
+//Pandora FMS- http://pandorafms.com
+// ==================================================
+// Copyright (c) 2005-2018 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 Lesser General Public License
+// as published by the Free Software Foundation; 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.
+
+global $config;
+
+require_once($config['homedir']."/include/class/Tree.class.php");
+
+class TreeService extends Tree {
+
+	protected $propagateCounters = true;
+	protected $displayAllGroups  = false;
+
+	public function  __construct($type, $rootType = '', $id = -1, $rootID = -1, $serverID = false, $childrenMethod = "on_demand", $access = 'AR') {
+		global $config;
+
+		parent::__construct($type, $rootType, $id, $rootID, $serverID, $childrenMethod, $access);
+
+		$this->L1fieldName = "id_group";
+		$this->L1extraFields = array(
+			"ts.name AS `name`",
+			"ts.id AS `sid`"
+		);
+
+		$this->filter['statusAgent'] = AGENT_STATUS_ALL;
+
+		$this->avoid_condition = true;
+
+		$this->L2inner = 'LEFT JOIN tservice_element tse
+									ON tse.id_agent = ta.id_agente';
+
+		$this->L2condition = 'AND tse.id_service='.$this->id;
+
+	}
+
+	public function setPropagateCounters($value) {
+		$this->propagateCounters = (bool)$value;
+	}
+
+	public function setDisplayAllGroups($value) {
+		$this->displayAllGroups = (bool)$value;
+	}
+
+	protected function getData() {
+		if ($this->id == -1) {
+			$this->getFirstLevel();
+		} elseif ($this->type == 'services') {
+			$this->getSecondLevel();
+		} elseif ($this->type == 'agent') {
+			$this->getThirdLevel();
+		}
+	}
+
+	protected function getFirstLevel() {
+		$processed_items = $this->getProcessedServices();
+		$ids = array_keys($processed_items);
+
+
+
+		$filter=array('id'=>$ids);
+
+		$own_info = get_user_info($config['id_user']);
+
+		if ($own_info['is_admin'] || check_acl($config['id_user'], 0, 'PM')) {
+		    $display_all_services = true;
+		} else {
+		    $display_all_services = false;
+		}
+
+        $this->tree = [];
+
+		$services = services_get_services($filter, false, $display_all_services);
+
+		foreach ($services as $row) {
+
+
+
+			$status = services_get_status($row, true);
+				
+			switch ($status) {
+
+			    case SERVICE_STATUS_NORMAL:
+					$processed_items[$row['id']]['statusImageHTML']='<img src="images/status_sets/default/agent_ok_ball.png" data-title="NORMAL status." data-use_title_for_force_title="1" class="forced_title" alt="NORMAL status." />';
+			    break;
+
+			    case SERVICE_STATUS_CRITICAL:
+					$processed_items[$row['id']]['statusImageHTML']='<img src="images/status_sets/default/agent_critical_ball.png" data-title="CRITICAL status." data-use_title_for_force_title="1" class="forced_title" alt="CRITICAL status." />';
+			    break;
+
+			    case SERVICE_STATUS_WARNING:
+					$processed_items[$row['id']][$key]['statusImageHTML']='<img src="images/status_sets/default/agent_warning_ball.png" data-title="WARNING status." data-use_title_for_force_title="1" class="forced_title" alt="WARNING status." />';
+			    break;
+
+			    case SERVICE_STATUS_UNKNOWN:
+			    default:
+					$processed_items[$row['id']]['statusImageHTML']='<img src="images/status_sets/default/agent_no_data_ball.png" data-title="UNKNOWN status." data-use_title_for_force_title="1" class="forced_title" alt="UNKNOWN status." />';
+			    break;
+			}
+		}
+
+		$this->tree = $processed_items;
+	}
+
+	protected function getProcessedServices () {
+		$fields = $this->getFirstLevelFields();
+
+		if (users_can_manage_group_all("AR")){
+		$groups_acl = "";
+		}
+		else{
+		  $groups_acl = "AND ts.id_group IN (".implode(',', $this->userGroupsArray).")";
+		 }
+
+		$sql = sprintf("SELECT t1.* 
+						FROM tservice_element tss
+						RIGHT JOIN
+						(SELECT ts.id, ts.id_agent_module, ts.name, ts.name AS `alias`, ts.id AS `rootID`,
+						'services' AS rootType, 'services' AS type,
+						0 AS quiet,
+						SUM(if((tse.id_agent<>0), 1, 0)) AS `total_agents`,
+						SUM(if((tse.id_agente_modulo<>0), 1, 0)) AS `total_modules`,
+						SUM(if((tse.id_service_child<>0), 1, 0)) AS `total_services`
+					FROM tservice ts
+					LEFT JOIN tservice_element tse
+						ON ts.id=tse.id_service
+					GROUP BY id
+					) as t1  
+					ON tss.id_service_child = t1.id
+					WHERE tss.id_service_child IS NULL
+					%s
+					",
+				$groups_acl
+			);
+
+
+		$stats = db_get_all_rows_sql($sql);
+
+
+
+
+		$services = array();
+
+		foreach ($stats as $service) {
+			$services[$service['id']] = $this->getProcessedItem($services[$service['id']]);
+			if ($service['total_services']+$service['total_agents']+$service['total_modules'] > 0)
+				$services[$service['id']]['searchChildren'] = 1;
+			else
+				$services[$service['id']]['searchChildren'] = 0;
+
+			$services[$service['id']]['counters'] = array('total_services'=>$service['total_services'], 'total_agents'=>$service['total_agents'], 'total_modules'=>$service['total_modules']);
+			$services[$service['id']]['name'] = $service['name'];
+			$services[$service['id']]['id'] = $service['id'];
+			$services[$service['id']]['serviceDetail']='index.php?sec=network&sec2=enterprise/operation/services/services&tab=service_map&id_service='.(int)$service['id'];
+		}
+
+		return $services;
+	}
+
+	protected function getFirstLevelFields() {
+		$fields = array();
+
+		return implode(",", array_merge($fields, $this->L1extraFields));
+	}
+
+	protected function getSecondLevel() {
+		$data = array();
+		$data_agents = array();
+		$data_modules = array();
+		$data_services = array();
+
+		$sql = $this->getSecondLevelSql();
+		$data_agents = db_process_sql($sql);
+
+		if (empty($data_agents))
+			$data_agents = array();
+
+		$this->processAgents($data_agents);
+
+		foreach ($data_agents as $key => $agent) {
+						$data_agents[$key]['showEventsBtn'] = 1;
+			$data_agents[$key]['eventAgent'] = $agent['id'];
+		}
+
+		$sql = $this->getSecondLevelModulesSql();
+		$data_modules = db_process_sql($sql);
+
+		if (empty($data_modules))
+			$data_modules = array();
+		else {
+			foreach ($data_modules as $key => $module) {
+				switch ($module['estado']) {
+					case '0':
+						$data_modules[$key]['statusImageHTML'] = '<img src="images/status_sets/default/agent_ok_ball.png" data-title="NORMAL status." data-use_title_for_force_title="1" class="forced_title" alt="NORMAL status." />';
+						break;
+					case '1':
+						$data_modules[$key]['statusImageHTML'] = '<img src="images/status_sets/default/agent_critical_ball.png" data-title="NORMAL status." data-use_title_for_force_title="1" class="forced_title" alt="CRITICAL status." />';
+						break;
+					case '2':
+						$data_modules[$key]['statusImageHTML'] = '<img src="images/status_sets/default/agent_warning_ball.png" data-title="NORMAL status." data-use_title_for_force_title="1" class="forced_title" alt="WARNING status." />';
+						break;
+					case '4':
+						$data_modules[$key]['statusImageHTML'] = '<img src="images/status_sets/default/agent_no_data_ball.png" data-title="NORMAL status." data-use_title_for_force_title="1" class="forced_title" alt="UNKNOWN status." />';
+						break;
+					default:
+						# code...
+						break;
+				}
+
+				$data_modules[$key]['showEventsBtn'] = 1;
+				$data_modules[$key]['eventModule'] = $module['id_agente_modulo'];	
+			}
+		}
+
+		$sql = $this->getSecondLevelServicesSql();
+		$data_services = db_process_sql($sql);
+
+
+		$service_stats = array();
+
+		foreach ($data_services as $service) {
+			$service_stats[$service['id']]['id'] = (int)$service['id'];
+			$service_stats[$service['id']]['name'] = $service['name'];
+			$service_stats[$service['id']]['alias'] = $service['name'];
+			if ($service['total_services']+$service['total_agents']+$service['total_modules'] > 0)
+				$service_stats[$service['id']]['searchChildren'] = 1;
+			else
+				$services[$service['id']]['searchChildren'] = 0;
+
+			$service_stats[$service['id']]['rootID'] = $service['rootID'];
+			$service_stats[$service['id']]['rootType'] = $service['rootType'];
+			$service_stats[$service['id']]['type'] = 'services';
+			$service_stats[$service['id']]['children']=array();
+			$service_stats[$service['id']]['serviceDetail']='index.php?sec=network&sec2=enterprise/operation/services/services&tab=service_map&id_service='.(int)$service['id'];
+			$service_stats[$service['id']]['counters']=array('total_services'=>$service['total_services'], 'total_agents'=>$service['total_agents'], 'total_modules'=>$service['total_modules']);
+
+		}
+
+		$own_info = get_user_info($config['id_user']);
+
+		if ($own_info['is_admin'] || check_acl($config['id_user'], 0, 'PM')) {
+		    $display_all_services = true;
+		} else {
+		    $display_all_services = false;
+		}
+
+		$services = services_get_services($filter, false, $display_all_services);
+
+		foreach ($services as $row) {
+
+			if (!array_key_exists($row['id'], $service_stats))
+				continue;
+
+			$status = services_get_status($row, true);
+
+
+			switch ($status) {
+
+			    case SERVICE_STATUS_NORMAL:
+					$service_stats[$row['id']]['statusImageHTML']='<img src="images/status_sets/default/agent_ok_ball.png" data-title="NORMAL status." data-use_title_for_force_title="1" class="forced_title" alt="NORMAL status." />';
+			    break;
+
+			    case SERVICE_STATUS_CRITICAL:
+					$service_stats[$row['id']]['statusImageHTML']='<img src="images/status_sets/default/agent_critical_ball.png" data-title="CRITICAL status." data-use_title_for_force_title="1" class="forced_title" alt="CRITICAL status." />';
+			    break;
+
+			    case SERVICE_STATUS_WARNING:
+					$service_stats[$row['id']][$key]['statusImageHTML']='<img src="images/status_sets/default/agent_warning_ball.png" data-title="WARNING status." data-use_title_for_force_title="1" class="forced_title" alt="WARNING status." />';
+			    break;
+
+			    case SERVICE_STATUS_UNKNOWN:
+			    default:
+					$service_stats[$row['id']]['statusImageHTML']='<img src="images/status_sets/default/agent_no_data_ball.png" data-title="UNKNOWN status." data-use_title_for_force_title="1" class="forced_title" alt="UNKNOWN status." />';
+			    break;
+			}
+		}
+	
+		$data_services = array_values($service_stats);
+
+		$data = array_merge($data_services, $data_agents, $data_modules);
+
+		if (empty($data)) {
+			$this->tree = array();
+			return;
+		}
+
+		$this->tree = $data;
+	}
+
+	protected function getSecondLevelServicesSql() {
+		$group_acl = $this->getGroupAclCondition();
+
+		$sql = "SELECT ts.id, ts.name, tse1.id_service AS `rootID`, 'services' AS rootType, 'services' AS type, 0 AS quiet, SUM(if((tse2.id_agent<>0), 1, 0)) AS `total_agents`, SUM(if((tse2.id_agente_modulo<>0), 1, 0)) AS `total_modules`, SUM(if((tse2.id_service_child<>0), 1, 0)) AS `total_services`, 0 AS fired_count, 0 AS normal_count, 0 AS warning_count, 0 AS critical_count, 0 AS unknown_count, 0 AS notinit_count, 0 AS state_critical, 0 AS state_warning, 0 AS state_unknown, 0 AS state_notinit, 0 AS state_normal, 0 AS state_total, '' AS statusImageHTML, '' AS alertImageHTML
+		FROM tservice_element tse1
+		LEFT JOIN tservice_element tse2 ON tse1.id_service_child=tse2.id_service
+		LEFT JOIN tservice ts ON tse1.id_service_child=ts.id
+		WHERE tse1.id_service=$this->id AND tse1.id_service_child<>0
+		GROUP BY tse1.id_service_child
+		";
+
+		return $sql;
+	}
+
+
+	protected function getSecondLevelModulesSql() {
+
+		$sql = "SELECT tse.id_agente_modulo, nombre AS `name`, nombre AS `alias`, tse.id_service AS `rootID`, 'services' AS `rootType`, 'modules' AS `type`, estado
+				FROM tservice_element tse
+				INNER JOIN tagente_modulo tam ON tse.id_agente_modulo=tam.id_agente_modulo
+				INNER JOIN tagente_estado tae ON tam.id_agente_modulo=tae.id_agente_estado
+				WHERE tse.id_service=$this->id AND tse.id_agente_modulo<>0
+		";
+
+		return $sql;
+	}
+
+	protected function getAgentStatusFilter ($status = self::TV_DEFAULT_AGENT_STATUS) {
+		return '';
+	}
+
+}
+
+?>
+
diff --git a/pandora_console/include/javascript/tree/TreeController.js b/pandora_console/include/javascript/tree/TreeController.js
index e3f7260de4..04e67e670b 100644
--- a/pandora_console/include/javascript/tree/TreeController.js
+++ b/pandora_console/include/javascript/tree/TreeController.js
@@ -13,895 +13,994 @@
 // GNU General Public License for more details.
 
 var TreeController = {
-  controllers: [],
-  getController: function() {
-    var controller = {
-      index: -1,
-      recipient: "",
-      tree: [],
-      emptyMessage: "No data found.",
-      foundMessage: "Found groups",
-      errorMessage: "Error",
-      baseURL: "",
-      ajaxURL: "ajax.php",
-      ajaxPage: "include/ajax/tree.ajax",
-      detailRecipient: "",
-      filter: {},
-      counterTitles: {},
-      shouldHaveCounters: true,
-      reload: function() {
-        // Bad recipient
-        if (
-          typeof this.recipient == "undefined" ||
-          this.recipient.length == 0
-        ) {
-          return;
-        }
-
-        // Load branch
-        function _processGroup(container, elements, rootGroup) {
-          var $group = $("<ul></ul>");
-
-          // First group
-          if (typeof rootGroup != "undefinded" && rootGroup == true) {
-            $group
-              .addClass("tree-root")
-              .hide()
-              .prepend(
-                '<img src="' +
-                  (controller.baseURL.length > 0 ? controller.baseURL : "") +
-                  'images/pandora.png" />'
-              );
-          }
-          // Normal group
-          else {
-            $group.addClass("tree-group").hide();
-          }
-
-          container.append($group);
-
-          _.each(elements, function(element) {
-            element.jqObject = _processNode($group, element);
-          });
-
-          return $group;
-        }
-
-        // Load leaf counters
-        function _processNodeCounters(container, counters, type) {
-          var hasCounters = false;
-
-          if (typeof counters != "undefined") {
-            function _processNodeCounterTitle(
-              container,
-              elementType,
-              counterType
-            ) {
-              var defaultCounterTitles = {
-                total: {
-                  agents: "Total agents",
-                  modules: "Total modules",
-                  none: "Total"
-                },
-                alerts: {
-                  agents: "Alerts fired",
-                  modules: "Alerts fired",
-                  none: "Alerts fired"
-                },
-                critical: {
-                  agents: "Critical agents",
-                  modules: "Critical modules",
-                  none: "Critical"
-                },
-                warning: {
-                  agents: "Warning agents",
-                  modules: "Warning modules",
-                  none: "Warning"
-                },
-                unknown: {
-                  agents: "Unknown agents",
-                  modules: "Unknown modules",
-                  none: "Unknown"
-                },
-                not_init: {
-                  agents: "Not init agents",
-                  modules: "Not init modules",
-                  none: "Not init"
-                },
-                ok: {
-                  agents: "Normal agents",
-                  modules: "Normal modules",
-                  none: "Normal"
-                }
-              };
-
-              try {
-                var title = "";
-                switch (elementType) {
-                  case "group":
-                    if (
-                      typeof controller.counterTitles != "undefined" &&
-                      typeof controller.counterTitles[counterType] !=
-                        "undefined" &&
-                      typeof controller.counterTitles[counterType].agents !=
-                        "undefined"
-                    ) {
-                      title = controller.counterTitles[counterType].agents;
-                    } else {
-                      title = defaultCounterTitles[counterType].agents;
-                    }
-                    break;
-                  case "agent":
-                    if (
-                      typeof controller.counterTitles != "undefined" &&
-                      typeof controller.counterTitles[counterType] !=
-                        "undefined" &&
-                      typeof controller.counterTitles[counterType].modules !=
-                        "undefined"
-                    ) {
-                      title = controller.counterTitles[counterType].modules;
-                    } else {
-                      title = defaultCounterTitles[counterType].modules;
-                    }
-                    break;
-                  default:
-                    if (
-                      typeof controller.counterTitles != "undefined" &&
-                      typeof controller.counterTitles[counterType] !=
-                        "undefined" &&
-                      typeof controller.counterTitles[counterType].none !=
-                        "undefined"
-                    ) {
-                      title = controller.counterTitles[counterType].none;
-                    } else {
-                      title = defaultCounterTitles[counterType].none;
-                    }
-                    break;
-                }
-                if (title.length > 0) {
-                  container
-                    .data("title", title)
-                    .addClass("forced_title")
-                    .data("use_title_for_force_title", 1); // Trick to make easier the 'force title' output
-                }
-              } catch (error) {
-                // console.log(error);
-              }
-            }
-
-            var $counters = $("<div></div>");
-            $counters.addClass("tree-node-counters");
-
-            if (typeof counters.total != "undefined" && counters.total >= 0) {
-              var $totalCounter = $("<div></div>");
-              $totalCounter
-                .addClass("tree-node-counter")
-                .addClass("total")
-                .html(counters.total);
-
-              _processNodeCounterTitle($totalCounter, type, "total");
-
-              // Open the parentheses
-              $counters.append(" (");
-
-              $counters.append($totalCounter);
-
-              if (
-                typeof counters.alerts != "undefined" &&
-                counters.alerts > 0
-              ) {
-                var $firedCounter = $("<div></div>");
-                $firedCounter
-                  .addClass("tree-node-counter")
-                  .addClass("alerts")
-                  .addClass("orange")
-                  .html(counters.alerts);
-
-                _processNodeCounterTitle($firedCounter, type, "alerts");
-
-                $counters.append(" : ").append($firedCounter);
-              }
-              if (
-                typeof counters.critical != "undefined" &&
-                counters.critical > 0
-              ) {
-                var $criticalCounter = $("<div></div>");
-                $criticalCounter
-                  .addClass("tree-node-counter")
-                  .addClass("critical")
-                  .addClass("red")
-                  .html(counters.critical);
-
-                _processNodeCounterTitle($criticalCounter, type, "critical");
-
-                $counters.append(" : ").append($criticalCounter);
-              }
-              if (
-                typeof counters.warning != "undefined" &&
-                counters.warning > 0
-              ) {
-                var $warningCounter = $("<div></div>");
-                $warningCounter
-                  .addClass("tree-node-counter")
-                  .addClass("warning")
-                  .addClass("yellow")
-                  .html(counters.warning);
-
-                _processNodeCounterTitle($warningCounter, type, "warning");
-
-                $counters.append(" : ").append($warningCounter);
-              }
-              if (
-                typeof counters.unknown != "undefined" &&
-                counters.unknown > 0
-              ) {
-                var $unknownCounter = $("<div></div>");
-                $unknownCounter
-                  .addClass("tree-node-counter")
-                  .addClass("unknown")
-                  .addClass("grey")
-                  .html(counters.unknown);
-
-                _processNodeCounterTitle($unknownCounter, type, "unknown");
-
-                $counters.append(" : ").append($unknownCounter);
-              }
-              if (
-                typeof counters.not_init != "undefined" &&
-                counters.not_init > 0
-              ) {
-                var $notInitCounter = $("<div></div>");
-                $notInitCounter
-                  .addClass("tree-node-counter")
-                  .addClass("not_init")
-                  .addClass("blue")
-                  .html(counters.not_init);
-
-                _processNodeCounterTitle($notInitCounter, type, "not_init");
-
-                $counters.append(" : ").append($notInitCounter);
-              }
-              if (typeof counters.ok != "undefined" && counters.ok > 0) {
-                var $okCounter = $("<div></div>");
-                $okCounter
-                  .addClass("tree-node-counter")
-                  .addClass("ok")
-                  .addClass("green")
-                  .html(counters.ok);
-
-                _processNodeCounterTitle($okCounter, type, "ok");
-
-                $counters.append(" : ").append($okCounter);
-              }
-
-              // Close the parentheses
-              $counters.append(")");
-
-              hasCounters = true;
-            }
-
-            // Add the counters html to the container
-            container.append($counters);
-          }
-
-          return hasCounters;
-        }
-
-        // Load leaf
-        function _processNode(container, element) {
-          // type, [id], [serverID], callback
-          function _getTreeDetailData(type, id, serverID, callback) {
-            var lastParam = arguments[arguments.length - 1];
-            var callback;
-            if (typeof lastParam === "function") callback = lastParam;
-
-            var serverID;
-            if (arguments.length >= 4) serverID = arguments[2];
-            var id;
-            if (arguments.length >= 3) id = arguments[1];
-            var type;
-            if (arguments.length >= 2) type = arguments[0];
-
-            if (typeof type === "undefined")
-              throw new TypeError("Type required");
-            if (typeof callback === "undefined")
-              throw new TypeError("Callback required");
-
-            var postData = {
-              page: controller.ajaxPage,
-              getDetail: 1,
-              type: type
-            };
-
-            if (typeof id !== "undefined") postData.id = id;
-            if (typeof serverID !== "undefined") postData.serverID = serverID;
-
-            $.ajax({
-              url: controller.ajaxURL,
-              type: "POST",
-              dataType: "html",
-              data: postData,
-              success: function(data, textStatus, xhr) {
-                callback(null, data);
-              },
-              error: function(xhr, textStatus, errorThrown) {
-                callback(errorThrown);
-              }
-            });
-          }
-
-          var $node = $("<li></li>");
-          var $leafIcon = $("<div></div>");
-          var $content = $("<div></div>");
-
-          // Leaf icon
-          $leafIcon.addClass("leaf-icon");
-
-          // Content
-          $content.addClass("node-content");
-          switch (element.type) {
-            case "group":
-              if (
-                typeof element.icon != "undefined" &&
-                element.icon.length > 0
-              ) {
-                $content.append(
-                  '<img src="' +
-                    (controller.baseURL.length > 0 ? controller.baseURL : "") +
-                    "images/groups_small/" +
-                    element.icon +
-                    '" /> '
-                );
-              } else if (
-                typeof element.iconHTML != "undefined" &&
-                element.iconHTML.length > 0
-              ) {
-                $content.append(element.iconHTML + " ");
-              }
-              $content.append(element.name);
-
-              if (typeof element.edit != "undefined") {
-                var url_edit =
-                  controller.baseURL +
-                  "index.php?sec=gagente&sec2=godmode/groups/configure_group&tab=tree&id_group=" +
-                  element.id;
-                var $updateicon = $(
-                  '<img src="' +
-                    (controller.baseURL.length > 0 ? controller.baseURL : "") +
-                    'images/config.png" style="width:18px; vertical-align: middle;"/>'
-                );
-                var $updatebtn = $('<a href = "' + url_edit + '"></a>').append(
-                  $updateicon
-                );
-                $content.append($updatebtn);
-              }
-
-              if (typeof element.delete != "undefined") {
-                var url_delete =
-                  controller.baseURL +
-                  "index.php?sec=gagente&sec2=godmode/groups/group_list&tab=tree&delete_group=1&id_group=" +
-                  element.id;
-                var $deleteBtn = $(
-                  '<a><img src="' +
-                    (controller.baseURL.length > 0 ? controller.baseURL : "") +
-                    'images/cross.png" style="width:18px; vertical-align: middle; cursor: pointer;"/></a>'
-                );
-                $deleteBtn.click(function(event) {
-                  var ok_function = function() {
-                    window.location.replace(url_delete);
-                  };
-                  display_confirm_dialog(
-                    element.delete.messages.messg,
-                    element.delete.messages.confirm,
-                    element.delete.messages.cancel,
-                    ok_function
-                  );
-                });
-                $content.append($deleteBtn);
-              }
-
-              if (typeof element.alerts != "undefined") {
-                $content.append(element.alerts);
-              }
-
-              break;
-            case "agent":
-              // Is quiet
-              if (
-                typeof element.quietImageHTML != "undefined" &&
-                element.quietImageHTML.length > 0
-              ) {
-                var $quietImage = $(element.quietImageHTML);
-                $quietImage.addClass("agent-quiet");
-
-                $content.append($quietImage);
-              }
-              // Status image
-              if (
-                typeof element.statusImageHTML != "undefined" &&
-                element.statusImageHTML.length > 0
-              ) {
-                var $statusImage = $(element.statusImageHTML);
-                $statusImage.addClass("agent-status");
-
-                $content.append($statusImage);
-              }
-              // Alerts fired image
-              if (
-                typeof element.alertImageHTML != "undefined" &&
-                element.alertImageHTML.length > 0
-              ) {
-                var $alertImage = $(element.alertImageHTML);
-                $alertImage.addClass("agent-alerts-fired");
-
-                $content.append($alertImage);
-              }
-              $content.append(element.alias);
-              break;
-            case "module":
-              // Status image
-              if (
-                typeof element.statusImageHTML != "undefined" &&
-                element.statusImageHTML.length > 0
-              ) {
-                var $statusImage = $(element.statusImageHTML);
-                $statusImage.addClass("module-status");
-
-                $content.append($statusImage);
-              }
-              // Server type
-              if (
-                typeof element.serverTypeHTML != "undefined" &&
-                element.serverTypeHTML.length > 0 &&
-                element.serverTypeHTML != "--"
-              ) {
-                var $serverTypeImage = $(element.serverTypeHTML);
-                $serverTypeImage.addClass("module-server-type");
-
-                $content.append($serverTypeImage);
-              }
-
-              if (
-                typeof element.showGraphs != "undefined" &&
-                element.showGraphs != 0
-              ) {
-                // Graph pop-up
-                if (typeof element.moduleGraph != "undefined") {
-                  if (element.statusImageHTML.indexOf("data:image") != -1) {
-                    var $graphImage = $(
-                      '<img src="' +
-                        (controller.baseURL.length > 0
-                          ? controller.baseURL
-                          : "") +
-                        'images/photo.png" /> '
-                    );
-                  } else {
-                    var $graphImage = $(
-                      '<img src="' +
-                        (controller.baseURL.length > 0
-                          ? controller.baseURL
-                          : "") +
-                        'images/chart_curve.png" /> '
-                    );
-                  }
-
-                  $graphImage.addClass("module-graph").click(function(e) {
-                    e.preventDefault();
-                    if (element.statusImageHTML.indexOf("data:image") != -1) {
-                      try {
-                        winopeng_var(
-                          decodeURI(element.snapshot[0]),
-                          element.snapshot[1],
-                          element.snapshot[2],
-                          element.snapshot[3]
-                        );
-                      } catch (error) {
-                        // console.log(error);
-                      }
-                    } else {
-                      try {
-                        winopeng(
-                          element.moduleGraph.url,
-                          element.moduleGraph.handle
-                        );
-                      } catch (error) {
-                        // console.log(error);
-                      }
-                    }
-                  });
-
-                  $content.append($graphImage);
-                }
-
-                // Data pop-up
-                if (typeof element.id != "undefined" && !isNaN(element.id)) {
-                  var $dataImage = $(
-                    '<img src="' +
-                      (controller.baseURL.length > 0
-                        ? controller.baseURL
-                        : "") +
-                      'images/binary.png" /> '
-                  );
-                  $dataImage.addClass("module-data").click(function(e) {
-                    e.preventDefault();
-
-                    try {
-                      var serverName =
-                        element.serverName.length > 0 ? element.serverName : "";
-                      if ($("#module_details_window").length > 0)
-                        show_module_detail_dialog(
-                          element.id,
-                          "",
-                          serverName,
-                          0,
-                          86400,
-                          element.name.replace(/&#x20;/g, " ")
-                        );
-                    } catch (error) {
-                      // console.log(error);
-                    }
-                  });
-
-                  $content.append($dataImage);
-                }
-              }
-
-              // Alerts
-              if (
-                typeof element.alertsImageHTML != "undefined" &&
-                element.alertsImageHTML.length > 0
-              ) {
-                var $alertsImage = $(element.alertsImageHTML);
-
-                $alertsImage
-                  .addClass("module-alerts")
-                  .click(function(e) {
-                    _getTreeDetailData(
-                      "alert",
-                      element.id,
-                      element.serverID,
-                      function(error, data) {
-                        if (error) {
-                          // console.error(error);
-                        } else {
-                          controller.detailRecipient
-                            .render(element.name, data)
-                            .open();
-                        }
-                      }
-                    );
-
-                    // Avoid the execution of the module detail event
-                    e.stopPropagation();
-                  })
-                  .css("cursor", "pointer");
-
-                $content.append($alertsImage);
-              }
-
-              $content.append(element.name);
-              break;
-            case "os":
-              if (
-                typeof element.icon != "undefined" &&
-                element.icon.length > 0
-              ) {
-                $content.append(
-                  '<img src="' +
-                    (controller.baseURL.length > 0 ? controller.baseURL : "") +
-                    "images/os_icons/" +
-                    element.icon +
-                    '" /> '
-                );
-              }
-              $content.append(element.name);
-              break;
-            case "tag":
-              if (
-                typeof element.icon != "undefined" &&
-                element.icon.length > 0
-              ) {
-                $content.append(
-                  '<img src="' +
-                    (controller.baseURL.length > 0 ? controller.baseURL : "") +
-                    "images/os_icons/" +
-                    element.icon +
-                    '" /> '
-                );
-              } else {
-                $content.append(
-                  '<img src="' +
-                    (controller.baseURL.length > 0 ? controller.baseURL : "") +
-                    'images/tag_red.png" /> '
-                );
-              }
-              $content.append(element.name);
-              break;
-            default:
-              $content.append(element.name);
-              break;
-          }
-
-          // Load the status counters
-          var hasCounters = _processNodeCounters(
-            $content,
-            element.counters,
-            element.type
-          );
-          //Don't show empty groups
-          if (element.type == "agent") {
-            if (!hasCounters) {
-              return;
-            }
-          }
-          // If exist the detail container, show the data
-          if (typeof controller.detailRecipient !== "undefined") {
-            if (element.type == "agent" || element.type == "module") {
-              $content
-                .click(function(e) {
-                  _getTreeDetailData(
-                    element.type,
-                    element.id,
-                    element.serverID,
-                    function(error, data) {
-                      if (error) {
-                        // console.error(error);
-                      } else {
-                        controller.detailRecipient
-                          .render(element.name, data)
-                          .open();
-                      }
-                    }
-                  );
-                })
-                .css("cursor", "pointer");
-            }
-          }
-
-          $node
-            .addClass("tree-node")
-            .append($leafIcon)
-            .append($content);
-
-          container.append($node);
-
-          $node.addClass("leaf-empty");
-
-          if (
-            typeof element.children != "undefined" &&
-            element.children.length > 0
-          ) {
-            $node.removeClass("leaf-empty").addClass("leaf-closed");
-
-            // Add children
-            var $children = _processGroup($node, element.children);
-            $node.data("children", $children);
-
-            if (
-              typeof element.searchChildren == "undefined" ||
-              !element.searchChildren
-            ) {
-              $leafIcon.click(function(e) {
-                e.preventDefault();
-
-                if ($node.hasClass("leaf-open")) {
-                  $node
-                    .removeClass("leaf-open")
-                    .addClass("leaf-closed")
-                    .data("children")
-                    .slideUp();
-                } else {
-                  $node
-                    .removeClass("leaf-closed")
-                    .addClass("leaf-open")
-                    .data("children")
-                    .slideDown();
-                }
-              });
-            }
-          }
-          // Get hash and user.
-          var public_hash = $("#hidden-publi_dash_tree_view_hash").val();
-          if (typeof public_hash === "undefined") public_hash = 0;
-          var public_user = $("#hidden-publi_dash_tree_view_id_user").val();
-          if (typeof public_user === "undefined") public_user = 0;
-
-          if (
-            typeof element.searchChildren != "undefined" &&
-            element.searchChildren
-          ) {
-            if (
-              element.rootType == "group_edition" &&
-              typeof element.children == "undefined"
-            ) {
-              $node.addClass("leaf-empty");
-            } else {
-              $node.removeClass("leaf-empty").addClass("leaf-closed");
-              $leafIcon.click(function(e) {
-                e.preventDefault();
-
-                if (
-                  !$node.hasClass("leaf-loading") &&
-                  !$node.hasClass("children-loaded") &&
-                  !$node.hasClass("leaf-empty")
-                ) {
-                  $node
-                    .removeClass("leaf-closed")
-                    .removeClass("leaf-error")
-                    .addClass("leaf-loading");
-
-                  $.ajax({
-                    url: controller.ajaxURL,
-                    type: "POST",
-                    dataType: "json",
-                    data: {
-                      page: controller.ajaxPage,
-                      getChildren: 1,
-                      id: element.id,
-                      type: element.type,
-                      rootID: element.rootID,
-                      serverID: element.serverID,
-                      rootType: element.rootType,
-                      filter: controller.filter,
-                      hash: public_hash,
-                      id_user: public_user
-                    },
-                    complete: function(xhr, textStatus) {
-                      $node.removeClass("leaf-loading");
-                      $node.addClass("children-loaded");
-                    },
-                    success: function(data, textStatus, xhr) {
-                      if (data.success) {
-                        var $group = $node.children("ul.tree-group");
-                        if (
-                          (typeof data.tree != "undefined" &&
-                            data.tree.length > 0) ||
-                          $group.length > 0
-                        ) {
-                          $node.addClass("leaf-open");
-
-                          if ($group.length <= 0) {
-                            $group = $("<ul></ul>");
-                            $group.addClass("tree-group").hide();
-                            $node.append($group);
-                          }
-
-                          _.each(data.tree, function(element) {
-                            element.jqObject = _processNode($group, element);
-                          });
-
-                          $group.slideDown();
-
-                          $node.data("children", $group);
-
-                          // Add again the hover event to the 'force_callback' elements
-                          forced_title_callback();
-                        } else {
-                          $node.addClass("leaf-empty");
-                        }
-                      } else {
-                        $node.addClass("leaf-error");
-                      }
-                    },
-                    error: function(xhr, textStatus, errorThrown) {
-                      $node.addClass("leaf-error");
-                    }
-                  });
-                } else if (!$node.hasClass("leaf-empty")) {
-                  if ($node.hasClass("leaf-open")) {
-                    $node
-                      .removeClass("leaf-open")
-                      .addClass("leaf-closed")
-                      .data("children")
-                      .slideUp();
-                  } else {
-                    $node
-                      .removeClass("leaf-closed")
-                      .addClass("leaf-open")
-                      .data("children")
-                      .slideDown();
-                  }
-                }
-              });
-            }
-          }
-
-          return $node;
-        }
-
-        if (controller.recipient.length == 0) {
-          return;
-        } else if (controller.tree.length == 0) {
-          controller.recipient.empty();
-          controller.recipient.html(
-            "<div>" + controller.emptyMessage + "</div>"
-          );
-          return;
-        }
-
-        controller.recipient.empty();
-        controller.recipient.html(
-          "<div> " +
-            controller.foundMessage +
-            ": " +
-            controller.tree.length +
-            "</div>" +
-            "<br/>"
-        );
-
-        var $children = _processGroup(this.recipient, this.tree, true);
-        $children.show();
-
-        controller.recipient.data("children", $children);
-
-        // Add again the hover event to the 'force_callback' elements
-        forced_title_callback();
-      },
-      load: function() {
-        this.reload();
-      },
-      changeTree: function(tree) {
-        this.tree = tree;
-        this.reload();
-      },
-      init: function(data) {
-        if (
-          typeof data.recipient !== "undefined" &&
-          data.recipient.length > 0
-        ) {
-          this.recipient = data.recipient;
-        }
-        if (typeof data.detailRecipient !== "undefined") {
-          this.detailRecipient = data.detailRecipient;
-        }
-        if (typeof data.tree !== "undefined") {
-          this.tree = data.tree;
-        }
-        if (
-          typeof data.emptyMessage !== "undefined" &&
-          data.emptyMessage.length > 0
-        ) {
-          this.emptyMessage = data.emptyMessage;
-        }
-        if (
-          typeof data.foundMessage !== "undefined" &&
-          data.foundMessage.length > 0
-        ) {
-          this.foundMessage = data.foundMessage;
-        }
-        if (
-          typeof data.errorMessage !== "undefined" &&
-          data.errorMessage.length > 0
-        ) {
-          this.errorMessage = data.errorMessage;
-        }
-        if (typeof data.baseURL !== "undefined" && data.baseURL.length > 0) {
-          this.baseURL = data.baseURL;
-        }
-        if (typeof data.ajaxURL !== "undefined" && data.ajaxURL.length > 0) {
-          this.ajaxURL = data.ajaxURL;
-        }
-        if (typeof data.ajaxPage !== "undefined" && data.ajaxPage.length > 0) {
-          this.ajaxPage = data.ajaxPage;
-        }
-        if (typeof data.filter !== "undefined") {
-          this.filter = data.filter;
-        }
-
-        this.load();
-      },
-      remove: function() {
-        if (typeof this.recipient != "undefined" && this.recipient.length > 0) {
-          this.recipient.empty();
-        }
-
-        if (this.index > -1) {
-          TreeController.controllers.splice(this.index, 1);
-        }
-      }
-    };
-    controller.index = TreeController.controllers.push(controller) - 1;
-
-    return controller;
-  }
-};
+	controllers: [],
+	getController: function () {
+		var controller = {
+			index: -1,
+			recipient: '',
+			tree: [],
+			emptyMessage: "No data found.",
+			foundMessage: "Found groups",
+			errorMessage: "Error",
+			baseURL: "",
+			ajaxURL: "ajax.php",
+			ajaxPage: "include/ajax/tree.ajax",
+			detailRecipient: '',
+			filter: {},
+			counterTitles: {},
+			shouldHaveCounters: true,
+			reload: function () {
+				// Bad recipient
+				if (typeof this.recipient == 'undefined' || this.recipient.length == 0) {
+					return;
+				}
+
+				// Load branch
+				function _processGroup (container, elements, rootGroup) {
+					
+					var $group = $("<ul></ul>");
+					
+					// First group
+					if (typeof rootGroup != 'undefinded' && rootGroup == true) {
+						$group
+							.addClass("tree-root")
+							.hide()
+							.prepend('<img src="'+(controller.baseURL.length > 0 ? controller.baseURL : '')+'images/pandora.png" />');
+					}
+					// Normal group
+					else {
+						$group
+							.addClass("tree-group")
+							.hide();
+					}
+
+					container.append($group);
+
+					_.each(elements, function(element) {
+						element.jqObject = _processNode($group, element);
+					});
+					
+					return $group;
+				}
+
+				// Load leaf counters
+				function _processNodeCounters (container, counters, type) {
+					var hasCounters = false;
+
+					if (typeof counters != 'undefined') {
+						
+						function _processNodeCounterTitle (container, elementType, counterType) {
+
+							var defaultCounterTitles = {
+								total: {
+									agents: "Total agents",
+									modules: "Total modules",
+									none: "Total"
+								},
+								alerts: {
+									agents: "Alerts fired",
+									modules: "Alerts fired",
+									none: "Alerts fired"
+								},
+								critical: {
+									agents: "Critical agents",
+									modules: "Critical modules",
+									none: "Critical"
+								},
+								warning: {
+									agents: "Warning agents",
+									modules: "Warning modules",
+									none: "Warning"
+								},
+								unknown: {
+									agents: "Unknown agents",
+									modules: "Unknown modules",
+									none: "Unknown"
+								},
+								not_init: {
+									agents: "Not init agents",
+									modules: "Not init modules",
+									none: "Not init"
+								},
+								ok: {
+									agents: "Normal agents",
+									modules: "Normal modules",
+									none: "Normal"
+								}
+							}
+
+							var serviceCounterTitles = {
+								total_services: {
+									totals: "Services"
+								},
+								total_agents: {
+									totals: "Agents"
+								},
+								total_modules: {
+									totals: "Modules"
+								}
+							}
+
+							try {
+
+								var title = '';
+
+								switch (elementType) {
+									case "group":
+										if (typeof controller.counterTitles != 'undefined'
+												&& typeof controller.counterTitles[counterType] != 'undefined'
+												&& typeof controller.counterTitles[counterType].agents != 'undefined') {
+											title = controller.counterTitles[counterType].agents;
+										}
+										else {
+											title = defaultCounterTitles[counterType].agents;
+										}
+										break;
+									case "agent":
+										if (typeof controller.counterTitles != 'undefined'
+												&& typeof controller.counterTitles[counterType] != 'undefined'
+												&& typeof controller.counterTitles[counterType].modules != 'undefined') {
+											title = controller.counterTitles[counterType].modules;
+										}
+										else {
+											title = defaultCounterTitles[counterType].modules;
+										}
+										break;
+									case "services":
+											title = serviceCounterTitles[counterType].totals;
+										break;
+									default:
+										if (typeof controller.counterTitles != 'undefined'
+												&& typeof controller.counterTitles[counterType] != 'undefined'
+												&& typeof controller.counterTitles[counterType].none != 'undefined') {
+											title = controller.counterTitles[counterType].none;
+										}
+										else {
+											title = defaultCounterTitles[counterType].none;
+										}
+										break;
+								}
+								if (title.length > 0) {
+									container
+										.data("title", title)
+										.addClass("forced_title")
+										.data("use_title_for_force_title", 1); // Trick to make easier the 'force title' output
+								}
+							}
+							catch (error) {
+								// console.log(error);
+							}
+						}
+
+
+						if (type=="services") {
+
+							var $counters = $("<div></div>");
+							$counters.addClass('tree-node-counters');
+
+							if (counters.total_services+counters.total_agents+counters.total_modules > 0) {
+															
+								// Open the parentheses
+								$counters.append(" (");
+
+								if (typeof counters.total_services != 'undefined'
+										&& counters.total_services >= 0) {
+									
+									var $servicesCounter = $("<div></div>");
+									$servicesCounter
+										.addClass('tree-node-counter')
+										.addClass('total')
+										.html(counters.total_services);
+									
+									_processNodeCounterTitle($servicesCounter, type, "total_services");
+															
+									$counters
+										.append($servicesCounter);
+								} else {
+									var $servicesCounter = $("<div></div>");
+									$servicesCounter
+										.addClass('tree-node-counter')
+										.addClass('total')
+										.html('0');
+
+									_processNodeCounterTitle($servicesCounter, type, "total_services");
+
+									$counters
+										.append($servicesCounter);
+								}
+
+								if (typeof counters.total_agents != 'undefined'
+										&& counters.total_agents > 0) {
+									var $agentsCounter = $("<div></div>");
+									$agentsCounter
+										.addClass('tree-node-counter')
+										.html(counters.total_agents);
+
+									_processNodeCounterTitle($agentsCounter, type, "total_agents");
+
+									$counters
+										.append(" : ")
+										.append($agentsCounter);
+								} else {
+									var $agentsCounter = $("<div></div>");
+									$agentsCounter
+										.addClass('tree-node-counter')
+										.addClass('total')
+										.html('0');
+
+									_processNodeCounterTitle($agentsCounter, type, "total_agents");
+
+									$counters
+										.append(" : ")
+										.append($agentsCounter);
+								}
+
+								if (typeof counters.total_modules != 'undefined'
+										&& counters.total_modules > 0) {
+									var $modulesCounter = $("<div></div>");
+									$modulesCounter
+										.addClass('tree-node-counter')
+										.addClass('total')
+										.html(counters.total_modules);
+
+									_processNodeCounterTitle($modulesCounter, type, "total_modules");
+									
+									$counters
+										.append(" : ")
+										.append($modulesCounter);
+								} else {
+									var $modulesCounter = $("<div></div>");
+									$modulesCounter
+										.addClass('tree-node-counter')
+										.addClass('total')
+										.html('0');
+
+									_processNodeCounterTitle($modulesCounter, type, "total_modules");
+
+									$counters
+										.append(" : ")
+										.append($modulesCounter);
+								}
+
+								// Close the parentheses
+								$counters.append(")");
+
+								hasCounters = true;
+							}
+						} else {
+
+							var $counters = $("<div></div>");
+							$counters.addClass('tree-node-counters');
+
+							if (typeof counters.total != 'undefined'
+									&& counters.total >= 0) {
+								
+									var $totalCounter = $("<div></div>");
+									$totalCounter
+										.addClass('tree-node-counter')
+										.addClass('total')
+										.html(counters.total);
+									
+									_processNodeCounterTitle($totalCounter, type, "total");
+															
+								// Open the parentheses
+								$counters.append(" (");
+
+								$counters.append($totalCounter);
+
+								if (typeof counters.alerts != 'undefined'
+										&& counters.alerts > 0) {
+									var $firedCounter = $("<div></div>");
+									$firedCounter
+										.addClass('tree-node-counter')
+										.addClass('alerts')
+										.addClass('orange')
+										.html(counters.alerts);
+
+									_processNodeCounterTitle($firedCounter, type, "alerts");
+
+									$counters
+										.append(" : ")
+										.append($firedCounter);
+								}
+								if (typeof counters.critical != 'undefined'
+										&& counters.critical > 0) {
+									var $criticalCounter = $("<div></div>");
+									$criticalCounter
+										.addClass('tree-node-counter')
+										.addClass('critical')
+										.addClass('red')
+										.html(counters.critical);
+
+									_processNodeCounterTitle($criticalCounter, type, "critical");
+									
+									$counters
+										.append(" : ")
+										.append($criticalCounter);
+								}
+								if (typeof counters.warning != 'undefined'
+										&& counters.warning > 0) {
+									var $warningCounter = $("<div></div>");
+									$warningCounter
+										.addClass('tree-node-counter')
+										.addClass('warning')
+										.addClass('yellow')
+										.html(counters.warning);
+
+									_processNodeCounterTitle($warningCounter, type, "warning");
+									
+									$counters
+										.append(" : ")
+										.append($warningCounter);
+								}
+								if (typeof counters.unknown != 'undefined'
+										&& counters.unknown > 0) {
+									var $unknownCounter = $("<div></div>");
+									$unknownCounter
+										.addClass('tree-node-counter')
+										.addClass('unknown')
+										.addClass('grey')
+										.html(counters.unknown);
+
+									_processNodeCounterTitle($unknownCounter, type, "unknown");
+									
+									$counters
+										.append(" : ")
+										.append($unknownCounter);
+								}
+								if (typeof counters.not_init != 'undefined'
+										&& counters.not_init > 0) {
+												var $notInitCounter = $("<div></div>");
+												$notInitCounter
+													.addClass('tree-node-counter')
+													.addClass('not_init')
+													.addClass('blue')
+													.html(counters.not_init);
+
+												_processNodeCounterTitle($notInitCounter, type, "not_init");
+												
+												$counters
+													.append(" : ")
+													.append($notInitCounter);
+								}
+								if (typeof counters.ok != 'undefined'
+										&& counters.ok > 0) {
+									var $okCounter = $("<div></div>");
+									$okCounter
+										.addClass('tree-node-counter')
+										.addClass('ok')
+										.addClass('green')
+										.html(counters.ok);
+
+									_processNodeCounterTitle($okCounter, type, "ok");
+									
+									$counters
+										.append(" : ")
+										.append($okCounter);
+								}
+							}
+
+							// Close the parentheses
+							$counters.append(")");
+
+							hasCounters = true;
+						}
+
+						// Add the counters html to the container
+						container.append($counters);
+					}
+
+					return hasCounters;
+				}
+
+				// Load leaf
+				function _processNode (container, element) {
+					// type, [id], [serverID], callback
+					function _getTreeDetailData (type, id, serverID, callback) {
+						var lastParam = arguments[arguments.length - 1];
+						var callback;
+						if (typeof lastParam === 'function')
+							callback = lastParam;
+
+						var serverID;
+						if (arguments.length >= 4)
+							serverID = arguments[2];
+						var id;
+						if (arguments.length >= 3)
+							id = arguments[1];
+						var type;
+						if (arguments.length >= 2)
+							type = arguments[0];
+
+						if (typeof type === 'undefined')
+							throw new TypeError('Type required');
+						if (typeof callback === 'undefined')
+							throw new TypeError('Callback required');
+
+						var postData = {
+							page: controller.ajaxPage,
+							getDetail: 1,
+							type: type
+						}
+
+						if (typeof id !== 'undefined')
+							postData.id = id;
+						if (typeof serverID !== 'undefined')
+							postData.serverID = serverID;
+
+						$.ajax({
+							url: controller.ajaxURL,
+							type: 'POST',
+							dataType: 'html',
+							data: postData,
+							success: function(data, textStatus, xhr) {
+								callback(null, data);
+							},
+							error: function(xhr, textStatus, errorThrown) {
+								callback(errorThrown);
+							}
+						});
+					}
+
+					var $node = $("<li></li>");
+					var $leafIcon = $("<div></div>");
+					var $content = $("<div></div>");
+
+					// Leaf icon
+					$leafIcon.addClass("leaf-icon");
+
+					// Content
+					$content.addClass("node-content");
+					switch (element.type) {
+						case 'group':
+							if (typeof element.icon != 'undefined' && element.icon.length > 0) {
+								$content.append('<img src="'+(controller.baseURL.length > 0 ? controller.baseURL : '')
+									+'images/groups_small/'+element.icon+'" /> ');
+							}
+							else if (typeof element.iconHTML != 'undefined' && element.iconHTML.length > 0) {
+								$content.append(element.iconHTML + " ");
+							}
+							$content.append(element.name);
+
+							if(typeof element.edit != 'undefined'){
+								var url_edit = controller.baseURL + "index.php?sec=gagente&sec2=godmode/groups/configure_group&tab=tree&id_group=" + element.id;
+								var $updateicon = $('<img src="' + (controller.baseURL.length > 0 ? controller.baseURL : '')+ 'images/config.png" style="width:18px; vertical-align: middle;"/>')
+								var $updatebtn = $('<a href = "' + url_edit + '"></a>')
+									.append($updateicon);
+								$content.append($updatebtn);
+							}
+
+							if(typeof element.delete != 'undefined'){
+								var url_delete = controller.baseURL + "index.php?sec=gagente&sec2=godmode/groups/group_list&tab=tree&delete_group=1&id_group=" + element.id;
+								var $deleteBtn = $('<a><img src="' + (controller.baseURL.length > 0 ? controller.baseURL : '') +'images/cross.png" style="width:18px; vertical-align: middle; cursor: pointer;"/></a>');
+								$deleteBtn.click(function (event){
+									var ok_function = function(){
+										window.location.replace(url_delete);
+									};
+									display_confirm_dialog(
+										element.delete.messages.messg,
+										element.delete.messages.confirm,
+										element.delete.messages.cancel,
+										ok_function
+									)
+								});
+								$content.append($deleteBtn);
+							}
+
+							if(typeof element.alerts != 'undefined'){
+								$content.append(element.alerts);
+							}
+
+							break;
+						case 'agent':
+							// Is quiet
+							if (typeof element.quietImageHTML != 'undefined'
+									&& element.quietImageHTML.length > 0) {
+								var $quietImage = $(element.quietImageHTML);
+								$quietImage.addClass("agent-quiet");
+
+								$content.append($quietImage);
+							}
+							// Status image
+							if (typeof element.statusImageHTML != 'undefined'
+									&& element.statusImageHTML.length > 0) {
+								var $statusImage = $(element.statusImageHTML);
+								$statusImage.addClass("agent-status");
+
+								$content.append($statusImage);
+							}
+							// Alerts fired image
+							if (typeof element.alertImageHTML != 'undefined'
+									&& element.alertImageHTML.length > 0) {
+								var $alertImage = $(element.alertImageHTML);
+								$alertImage.addClass("agent-alerts-fired");
+
+								$content.append($alertImage);
+							}
+
+							// Events by agent
+							if (element.showEventsBtn == 1) {
+								if (typeof element.eventAgent != 'undefined') {
+
+									$content.append('<form method="post" id="hiddenAgentsEventsForm-'+element.eventAgent+'" style="display: none;" action="index.php?sec=eventos&sec2=operation/events/events&refr=0&pure=&section=list&history=0"><input type="hidden" name="id_agent" value="'+element.eventAgent+'"></form>');
+									var $eventImage = $('<img src="'+(controller.baseURL.length > 0 ? controller.baseURL : '')
+									+'images/tree_events.png" /> ');
+									$eventImage.addClass("agent-alerts-fired");
+									$eventImage
+										.click(function (e) {
+											e.preventDefault();
+
+											document.getElementById('hiddenAgentsEventsForm-'+element.eventAgent).submit();
+										})
+										.css('cursor', 'pointer');
+
+									$content.append($eventImage);
+								}
+							}
+
+							$content.append(' '+element.alias);
+							break;
+						case 'services':
+
+							if (typeof element.statusImageHTML != 'undefined'
+									&& element.statusImageHTML.length > 0) {
+								var $statusImage = $(element.statusImageHTML);
+								$statusImage.addClass("agent-status");
+
+								$content.append($statusImage);
+							}
+
+
+							var $serviceDetailImage = $('<img src="'+(controller.baseURL.length > 0 ? controller.baseURL : '')
+									+'images/tree_service_map.png" /> ');
+
+							if (typeof element.serviceDetail != 'undefined') {
+
+								$serviceDetailImage
+										.click(function (e) {
+											e.preventDefault();
+
+											window.location.href = element.serviceDetail;
+										})
+										.css('cursor', 'pointer');
+
+								$content.append($serviceDetailImage);
+							}
+
+							$content.append(' '+element.name);
+
+
+
+							
+							break;
+						case 'modules':
+							if (typeof element.statusImageHTML != 'undefined'
+									&& element.statusImageHTML.length > 0) {
+								var $statusImage = $(element.statusImageHTML);
+								$statusImage.addClass("agent-status");
+
+								$content.append($statusImage);
+							}
+
+							// Events by module
+							if (element.showEventsBtn == 1) {
+								if (typeof element.eventModule != 'undefined') {
+
+									$content.append('<form method="post" id="hiddenModulesEventsForm-'+element.eventModule+'" style="display: none;" action="index.php?sec=eventos&sec2=operation/events/events&refr=0&pure=&section=list&history=0"><input type="hidden" name="module_search_hidden" value="'+element.eventModule+'"></form>');
+									var $moduleImage = $('<img src="'+(controller.baseURL.length > 0 ? controller.baseURL : '')
+									+'images/tree_events.png" /> ');
+									$moduleImage
+										.click(function (e) {
+											e.preventDefault();
+
+											document.getElementById('hiddenModulesEventsForm-'+element.eventModule).submit();
+										})
+										.css('cursor', 'pointer');
+
+									$content.append($moduleImage);
+								}
+							}
+
+							$content.append(' '+element.name);
+							break;
+						case 'module':
+							// Status image
+							if (typeof element.statusImageHTML != 'undefined'
+									&& element.statusImageHTML.length > 0) {
+								var $statusImage = $(element.statusImageHTML);
+								$statusImage.addClass("module-status");
+
+								$content.append($statusImage);
+							}
+							// Server type
+							if (typeof element.serverTypeHTML != 'undefined'
+									&& element.serverTypeHTML.length > 0
+									&& element.serverTypeHTML != '--') {
+								var $serverTypeImage = $(element.serverTypeHTML);
+								$serverTypeImage.addClass("module-server-type");
+
+								$content.append($serverTypeImage);
+							}
+							
+							if (typeof element.showGraphs != 'undefined' && element.showGraphs != 0) {
+								// Graph pop-up
+								if (typeof element.moduleGraph != 'undefined') {
+									
+									if(element.statusImageHTML.indexOf('data:image')!=-1){
+									var $graphImage = $('<img src="'+(controller.baseURL.length > 0 ? controller.baseURL : '')
+											+'images/photo.png" /> ');
+									}
+									else{
+									
+									var $graphImage = $('<img src="'+(controller.baseURL.length > 0 ? controller.baseURL : '')
+											+'images/chart_curve.png" /> ');
+									}
+
+									$graphImage
+										.addClass('module-graph')
+										.click(function (e) {
+											e.preventDefault();
+											if(element.statusImageHTML.indexOf('data:image')!=-1){
+												try {
+													winopeng_var(
+														decodeURI(element.snapshot[0]),
+														element.snapshot[1],
+														element.snapshot[2],
+														element.snapshot[3]
+													);
+												}
+												catch (error) {
+													// console.log(error);
+												}
+											}
+											else{
+												try {
+													winopeng(element.moduleGraph.url, element.moduleGraph.handle);
+												}
+												catch (error) {
+													// console.log(error);
+												}
+											}
+										});
+
+									$content.append($graphImage);
+								}
+								
+								// Data pop-up
+								if (typeof element.id != 'undefined' && !isNaN(element.id)) {
+
+									var $dataImage = $('<img src="'+(controller.baseURL.length > 0 ? controller.baseURL : '')
+											+'images/binary.png" /> ');
+									$dataImage
+										.addClass('module-data')
+										.click(function (e) {
+											e.preventDefault();
+
+											try {
+												var serverName = element.serverName.length > 0 ? element.serverName : '';
+												if ($("#module_details_window").length > 0)
+													show_module_detail_dialog(element.id, '', serverName, 0, 86400, element.name.replace(/&#x20;/g , " ") );
+											}
+											catch (error) {
+												// console.log(error);
+											}
+										});
+
+									$content.append($dataImage);
+								}
+							}
+
+							// Alerts
+							if (typeof element.alertsImageHTML != 'undefined'
+									&& element.alertsImageHTML.length > 0) {
+
+								var $alertsImage = $(element.alertsImageHTML);
+
+								$alertsImage
+									.addClass("module-alerts")
+									.click(function (e) {
+										_getTreeDetailData('alert', element.id, element.serverID, function (error, data) {
+											if (error) {
+												// console.error(error);
+											}
+											else {
+												controller.detailRecipient.render(element.name, data).open();
+											}
+										});
+
+										// Avoid the execution of the module detail event
+										e.stopPropagation();
+									})
+									.css('cursor', 'pointer');
+
+								$content.append($alertsImage);
+							}
+
+							$content.append(element.name);
+							break;
+						case 'os':
+							if (typeof element.icon != 'undefined' && element.icon.length > 0) {
+								$content.append('<img src="'+(controller.baseURL.length > 0 ? controller.baseURL : '')
+									+'images/os_icons/'+element.icon+'" /> ');
+							}
+							$content.append(element.name);
+							break;
+						case 'tag':
+							if (typeof element.icon != 'undefined' && element.icon.length > 0) {
+								$content.append('<img src="'+(controller.baseURL.length > 0 ? controller.baseURL : '')
+									+'images/os_icons/'+element.icon+'" /> ');
+							}
+							else {
+								$content.append('<img src="'+(controller.baseURL.length > 0 ? controller.baseURL : '')
+									+'images/tag_red.png" /> ');
+							}
+							$content.append(element.name);
+							break;
+						case 'services':
+							// Status image
+							if (typeof element.statusImageHTML != 'undefined'
+									&& element.statusImageHTML.length > 0) {
+								var $statusImage = $(element.statusImageHTML);
+								$statusImage.addClass("agent-status");
+
+								$content.append($statusImage);
+							}
+							$content.append(element.name);
+							break;
+						default:
+							$content.append(element.name);
+							break;
+					}
+
+					// Load the status counters
+					var hasCounters = _processNodeCounters($content, element.counters, element.type);
+					//Don't show empty groups
+					if (element.type == 'agent') {
+						if (!hasCounters) {
+							return;
+						}
+					}
+					// If exist the detail container, show the data
+					if (typeof controller.detailRecipient !== 'undefined') {
+						if (element.type == 'agent' || element.type == 'module') {
+							$content.click(function (e) {
+									_getTreeDetailData(element.type, element.id, element.serverID, function (error, data) {
+										if (error) {
+											// console.error(error);
+										}
+										else {
+											controller.detailRecipient.render(element.name, data).open();
+										}
+									});
+								})
+								.css('cursor', 'pointer');
+						}
+					}
+
+					$node
+						.addClass("tree-node")
+						.append($leafIcon)
+						.append($content);
+
+					container.append($node);
+
+					$node.addClass("leaf-empty");
+
+					if (typeof element.children != 'undefined' && element.children.length > 0) {
+						$node
+							.removeClass("leaf-empty")
+							.addClass("leaf-closed");
+
+						// Add children
+						var $children = _processGroup($node, element.children);
+						$node.data('children', $children);
+
+						if (typeof element.searchChildren == 'undefined' || !element.searchChildren) {
+							$leafIcon.click(function (e) {
+								e.preventDefault();
+
+								if ($node.hasClass("leaf-open")) {
+									$node
+										.removeClass("leaf-open")
+										.addClass("leaf-closed")
+										.data('children')
+											.slideUp();
+								}
+								else {
+									$node
+										.removeClass("leaf-closed")
+										.addClass("leaf-open")
+										.data('children')
+											.slideDown();
+								}
+							});
+						}
+					}
+					// Get hash and user.
+					var public_hash = $("#hidden-publi_dash_tree_view_hash" ).val();
+					if (typeof(public_hash) === 'undefined') public_hash = 0;
+					var public_user = $("#hidden-publi_dash_tree_view_id_user" ).val();
+					if (typeof(public_user) === 'undefined') public_user = 0;
+
+					if (typeof element.searchChildren != 'undefined' && element.searchChildren) {
+						if(element.rootType == "group_edition"
+							&& typeof element.children == 'undefined'){
+							$node.addClass("leaf-empty");
+						}
+						else{
+							$node
+								.removeClass("leaf-empty")
+								.addClass("leaf-closed");
+							$leafIcon.click(function (e) {
+								e.preventDefault();
+
+								if (!$node.hasClass("leaf-loading") && !$node.hasClass("children-loaded") && !$node.hasClass("leaf-empty")) {
+									$node
+										.removeClass("leaf-closed")
+										.removeClass("leaf-error")
+										.addClass("leaf-loading");
+
+									$.ajax({
+										url: controller.ajaxURL,
+										type: 'POST',
+										dataType: 'json',
+										data: {
+											page: controller.ajaxPage,
+											getChildren: 1,
+											id: element.id,
+											type: element.type,
+											rootID: element.rootID,
+											serverID: element.serverID,
+											rootType: element.rootType,
+											filter: controller.filter,
+											hash: public_hash,
+											id_user: public_user
+										},
+										complete: function(xhr, textStatus) {
+											$node.removeClass("leaf-loading");
+											$node.addClass("children-loaded");
+										},
+										success: function(data, textStatus, xhr) {
+											if (data.success) {
+												var $group = $node.children("ul.tree-group");
+												if ((typeof data.tree != 'undefined' && data.tree.length > 0) || $group.length > 0) {
+													$node.addClass("leaf-open");
+
+													if ($group.length <= 0) {
+														$group = $("<ul></ul>");
+														$group
+															.addClass("tree-group")
+															.hide();
+														$node.append($group);
+													}
+
+													_.each(data.tree, function(element) {
+														element.jqObject = _processNode($group, element);
+													});
+
+													$group.slideDown();
+
+													$node.data('children', $group);
+
+													// Add again the hover event to the 'force_callback' elements
+													forced_title_callback();
+												}
+												else {
+													$node.addClass("leaf-empty");
+												}
+											}
+											else {
+												$node.addClass("leaf-error");
+											}
+										},
+										error: function(xhr, textStatus, errorThrown) {
+											$node.addClass("leaf-error");
+										}
+									});
+								}
+								else if (! $node.hasClass("leaf-empty")) {
+									if ($node.hasClass("leaf-open")) {
+										$node
+											.removeClass("leaf-open")
+											.addClass("leaf-closed")
+											.data('children')
+												.slideUp();
+									}
+									else {
+										$node
+											.removeClass("leaf-closed")
+											.addClass("leaf-open")
+											.data('children')
+												.slideDown();
+									}
+								}
+							});
+						}
+					}
+
+					return $node;
+				}
+
+				if (controller.recipient.length == 0) {
+					return;
+				}
+				else if (controller.tree.length == 0) {
+					controller.recipient.empty();
+					controller.recipient.html("<div>" + controller.emptyMessage + "</div>");
+					return;
+				}
+
+				controller.recipient.empty();
+        			if (controller.tree.length !== undefined) {
+	  				controller.recipient.html(
+	  					"<div> " +
+	  						controller.foundMessage +  ": " + controller.tree.length +
+	  					"</div>" +
+	  					"<br/>"
+	  				);
+        			}
+
+				var $children = _processGroup(this.recipient, this.tree, true);
+				$children.show();
+
+				controller.recipient.data('children', $children);
+
+				// Add again the hover event to the 'force_callback' elements
+				forced_title_callback();
+			},
+			load: function () {
+				this.reload();
+			},
+			changeTree: function (tree) {
+				this.tree = tree;
+				this.reload();
+			},
+			init: function (data) {
+				if (typeof data.recipient !== 'undefined' && data.recipient.length > 0) {
+					this.recipient = data.recipient;
+				}
+				if (typeof data.detailRecipient !== 'undefined') {
+					this.detailRecipient = data.detailRecipient;
+				}
+				if (typeof data.tree !== 'undefined') {
+					this.tree = data.tree;
+				}
+				if (typeof data.emptyMessage !== 'undefined' && data.emptyMessage.length > 0) {
+					this.emptyMessage = data.emptyMessage;
+				}
+				if (typeof data.foundMessage !== 'undefined' && data.foundMessage.length > 0) {
+					this.foundMessage = data.foundMessage;
+				}
+				if (typeof data.errorMessage !== 'undefined' && data.errorMessage.length > 0) {
+					this.errorMessage = data.errorMessage;
+				}
+				if (typeof data.baseURL !== 'undefined' && data.baseURL.length > 0) {
+					this.baseURL = data.baseURL;
+				}
+				if (typeof data.ajaxURL !== 'undefined' && data.ajaxURL.length > 0) {
+					this.ajaxURL = data.ajaxURL;
+				}
+				if (typeof data.ajaxPage !== 'undefined' && data.ajaxPage.length > 0) {
+					this.ajaxPage = data.ajaxPage;
+				}
+				if (typeof data.filter !== 'undefined') {
+					this.filter = data.filter;
+				}
+				
+				this.load();
+			},
+			remove: function () {
+				if (typeof this.recipient != 'undefined' && this.recipient.length > 0) {
+					this.recipient.empty();
+				}
+				
+				if (this.index > -1) {
+					TreeController.controllers.splice(this.index, 1);
+				}
+			}
+		}
+		controller.index = TreeController.controllers.push(controller) - 1;
+
+		return controller;
+	}
+}
diff --git a/pandora_console/operation/tree.php b/pandora_console/operation/tree.php
index fde9586325..3491f71458 100755
--- a/pandora_console/operation/tree.php
+++ b/pandora_console/operation/tree.php
@@ -278,226 +278,228 @@ enterprise_hook('close_meta_frame');
 <?php } ?>
 
 <script type="text/javascript">
-    var treeController = TreeController.getController();
-    
-    processTreeSearch();
-    
-    $("form#tree_search").submit(function(e) {
-        e.preventDefault();
-        processTreeSearch();
-    });
-    
-    function processTreeSearch () {
-        // Clear the tree
-        if (typeof treeController.recipient != 'undefined' && treeController.recipient.length > 0)
-            treeController.recipient.empty();
-        
-        $(".loading_tree").show();
-        
-        var parameters = {};
-        parameters['page'] = "include/ajax/tree.ajax";
-        parameters['getChildren'] = 1;
-        parameters['type'] = "<?php echo $tab; ?>";
-        parameters['filter'] = {};
-        parameters['filter']['searchGroup'] = $("input#text-search_group").val();
-        parameters['filter']['searchAgent'] = $("input#text-search_agent").val();
-        parameters['filter']['statusAgent'] = $("select#status_agent").val();
-        parameters['filter']['searchModule'] = $("input#text-search_module").val();
-        parameters['filter']['statusModule'] = $("select#status_module").val();
-        parameters['filter']['groupID'] = $("input#hidden-group-id").val();
-        parameters['filter']['tagID'] = $("input#hidden-tag-id").val();
-        
-        if($("#checkbox-serach_hirearchy").is(':checked')){
-            parameters['filter']['searchHirearchy'] = 1;
-        }
-        else{
-            parameters['filter']['searchHirearchy'] = 0;
-        }
-        
-        if($("#checkbox-show_not_init_agents").is(':checked')){
-            parameters['filter']['show_not_init_agents'] = 1;
-        }
-        else{
-            parameters['filter']['show_not_init_agents'] = 0;
-        }
-        
-        if($("#checkbox-show_not_init_modules").is(':checked')){
-            parameters['filter']['show_not_init_modules'] = 1;
-            $('#hidden-show_not_init_modules_hidden').val(1);
-        }
-        else{
-            parameters['filter']['show_not_init_modules'] = 0;
-            $('#hidden-show_not_init_modules_hidden').val(0);
-        }
+	var treeController = TreeController.getController();
+	
+	processTreeSearch();
+	
+	$("form#tree_search").submit(function(e) {
+		e.preventDefault();
+		processTreeSearch();
+	});
+	
+	function processTreeSearch () {
+		// Clear the tree
+		if (typeof treeController.recipient != 'undefined' && treeController.recipient.length > 0)
+			treeController.recipient.empty();
+		
+		$(".loading_tree").show();
+		
 
-        $.ajax({
-            type: "POST",
-            url: "<?php echo ui_get_full_url('ajax.php', false, false, false); ?>",
-            data: parameters,
-            success: function(data) {
-                if (data.success) {
-                    $(".loading_tree").hide();
-                    
-                    treeController.init({
-                        recipient: $("div#tree-controller-recipient"),
-                        detailRecipient: $.fixedBottomBox({ width: 400, height: window.innerHeight * 0.9 }),
-                        page: parameters['page'],
-                        emptyMessage: "<?php echo __('No data found'); ?>",
-                        foundMessage: "<?php echo __('Found groups'); ?>",
-                        tree: data.tree,
-                        baseURL: "<?php echo ui_get_full_url(false, false, false, is_metaconsole()); ?>",
-                        ajaxURL: "<?php echo ui_get_full_url('ajax.php', false, false, false); ?>",
-                        filter: parameters['filter'],
-                        counterTitles: {
-                            total: {
-                                agents: "<?php echo __('Total agents'); ?>",
-                                modules: "<?php echo __('Total modules'); ?>",
-                                none: "<?php echo __('Total'); ?>"
-                            },
-                            alerts: {
-                                agents: "<?php echo __('Fired alerts'); ?>",
-                                modules: "<?php echo __('Fired alerts'); ?>",
-                                none: "<?php echo __('Fired alerts'); ?>"
-                            },
-                            critical: {
-                                agents: "<?php echo __('Critical agents'); ?>",
-                                modules: "<?php echo __('Critical modules'); ?>",
-                                none: "<?php echo __('Critical'); ?>"
-                            },
-                            warning: {
-                                agents: "<?php echo __('Warning agents'); ?>",
-                                modules: "<?php echo __('Warning modules'); ?>",
-                                none: "<?php echo __('Warning'); ?>"
-                            },
-                            unknown: {
-                                agents: "<?php echo __('Unknown agents'); ?>",
-                                modules: "<?php echo __('Unknown modules'); ?>",
-                                none: "<?php echo __('Unknown'); ?>"
-                            },
-                            not_init: {
-                                agents: "<?php echo __('Not init agents'); ?>",
-                                modules: "<?php echo __('Not init modules'); ?>",
-                                none: "<?php echo __('Not init'); ?>"
-                            },
-                            ok: {
-                                agents: "<?php echo __('Normal agents'); ?>",
-                                modules: "<?php echo __('Normal modules'); ?>",
-                                none: "<?php echo __('Normal'); ?>"
-                            }
-                        }
-                    });
-                }
-            },
-            dataType: "json"
-        });
-    }
-    
-    // Show the modal window of an module
-    var moduleDetailsWindow = $("<div></div>");
-    moduleDetailsWindow
-        .hide()
-        .prop("id", "module_details_window")
-        .appendTo('body');
-    
-    function show_module_detail_dialog(module_id, id_agent, server_name, offset, period, module_name) {
-        var params = {};
-        var f = new Date();
-        period = $('#period').val();
-        
-        params.selection_mode = $('input[name=selection_mode]:checked').val();
-        if (!params.selection_mode) {
-            params.selection_mode='fromnow';
-        }
-        
-        params.date_from = $('#text-date_from').val();
-        if (!params.date_from) {
-            params.date_from = f.getFullYear() + "/" + (f.getMonth() +1) + "/" + f.getDate();
-        }
-        
-        params.time_from = $('#text-time_from').val();
-        if (!params.time_from) {
-            params.time_from = f.getHours() + ":"  + f.getMinutes();
-        }
-        
-        params.date_to = $('#text-date_to').val();
-        if (!params.date_to) {
-            params.date_to =f.getFullYear() + "/" + (f.getMonth() +1) + "/" + f.getDate();
-        }
-        
-        params.time_to = $('#text-time_to').val();
-        if (!params.time_to) {
-            params.time_to = f.getHours() + ":"  + f.getMinutes();
-        }
-        
-        params.page = "include/ajax/module";
-        params.get_module_detail = 1;
-        params.server_name = server_name;
-        params.id_agent = id_agent;
-        params.id_module = module_id;
-        params.offset = offset;
-        params.period = period;
-        title =   <?php echo "'".__('Module: ')."'"; ?> ;
-        $.ajax({
-            type: "POST",
-            url: "<?php echo ui_get_full_url('ajax.php', false, false, false); ?>",
-            data: params,
-            dataType: "html",
-            success: function(data) {
-                $("#module_details_window").hide ()
-                    .empty ()
-                    .append (data)
-                    .dialog ({
-                        resizable: true,
-                        draggable: true,
-                        modal: true,
-                        title: title + module_name,
-                        overlay: {
-                            opacity: 0.5,
-                            background: "black"
-                        },
-                        width: 650,
-                        height: 500
-                    })
-                    .show ();
-                    refresh_pagination_callback(module_id, id_agent, server_name, module_name);
-                    datetime_picker_callback();
-                    forced_title_callback();
-            }
-        });
-    }
-    
-    function datetime_picker_callback() {
-        $("#text-time_from, #text-time_to").timepicker({
-            showSecond: true,
-            timeFormat: '<?php echo TIME_FORMAT_JS; ?>',
-            timeOnlyTitle: '<?php echo __('Choose time'); ?>',
-            timeText: '<?php echo __('Time'); ?>',
-            hourText: '<?php echo __('Hour'); ?>',
-            minuteText: '<?php echo __('Minute'); ?>',
-            secondText: '<?php echo __('Second'); ?>',
-            currentText: '<?php echo __('Now'); ?>',
-            closeText: '<?php echo __('Close'); ?>'});
-        
-        $.datepicker.setDefaults($.datepicker.regional[ "<?php echo get_user_language(); ?>"]);
-        $("#text-date_from, #text-date_to").datepicker({dateFormat: "<?php echo DATE_FORMAT_JS; ?>"});
-        
-    }
-    
-    function refresh_pagination_callback (module_id, id_agent, server_name,module_name) {
-        
-        $(".binary_dialog").click( function() {
-            
-            var classes = $(this).attr('class');
-            classes = classes.split(' ');
-            var offset_class = classes[2];
-            offset_class = offset_class.split('_');
-            var offset = offset_class[1];
-            
-            var period = $('#period').val();
-            
-            show_module_detail_dialog(module_id, id_agent, server_name, offset, period,module_name);
-            return false;
-        });
-    }
-    
+
+		var parameters = {};
+		parameters['page'] = "include/ajax/tree.ajax";
+		parameters['getChildren'] = 1;
+		parameters['type'] = "<?php echo $tab; ?>";
+		parameters['filter'] = {};
+		parameters['filter']['searchGroup'] = $("input#text-search_group").val();
+		parameters['filter']['searchAgent'] = $("input#text-search_agent").val();
+		parameters['filter']['statusAgent'] = $("select#status_agent").val();
+		parameters['filter']['searchModule'] = $("input#text-search_module").val();
+		parameters['filter']['statusModule'] = $("select#status_module").val();
+		parameters['filter']['groupID'] = $("input#hidden-group-id").val();
+		parameters['filter']['tagID'] = $("input#hidden-tag-id").val();
+		
+		if($("#checkbox-serach_hirearchy").is(':checked')){
+			parameters['filter']['searchHirearchy'] = 1;
+		}
+		else{
+			parameters['filter']['searchHirearchy'] = 0;
+		}
+		
+		if($("#checkbox-show_not_init_agents").is(':checked')){
+			parameters['filter']['show_not_init_agents'] = 1;
+		}
+		else{
+			parameters['filter']['show_not_init_agents'] = 0;
+		}
+		
+		if($("#checkbox-show_not_init_modules").is(':checked')){
+			parameters['filter']['show_not_init_modules'] = 1;
+			$('#hidden-show_not_init_modules_hidden').val(1);
+		}
+		else{
+			parameters['filter']['show_not_init_modules'] = 0;
+			$('#hidden-show_not_init_modules_hidden').val(0);
+		}
+
+		$.ajax({
+			type: "POST",
+			url: "<?php echo ui_get_full_url('ajax.php', false, false, false); ?>",
+			data: parameters,
+			success: function(data) {
+				if (data.success) {
+					$(".loading_tree").hide();
+					
+					treeController.init({
+						recipient: $("div#tree-controller-recipient"),
+						detailRecipient: $.fixedBottomBox({ width: 400, height: window.innerHeight * 0.9 }),
+						page: parameters['page'],
+						emptyMessage: "<?php echo __('No data found'); ?>",
+						foundMessage: "<?php echo __('Found groups'); ?>",
+						tree: data.tree,
+						baseURL: "<?php echo ui_get_full_url(false, false, false, is_metaconsole()); ?>",
+						ajaxURL: "<?php echo ui_get_full_url('ajax.php', false, false, false); ?>",
+						filter: parameters['filter'],
+						counterTitles: {
+							total: {
+								agents: "<?php echo __('Total agents'); ?>",
+								modules: "<?php echo __('Total modules'); ?>",
+								none: "<?php echo __('Total'); ?>"
+							},
+							alerts: {
+								agents: "<?php echo __('Fired alerts'); ?>",
+								modules: "<?php echo __('Fired alerts'); ?>",
+								none: "<?php echo __('Fired alerts'); ?>"
+							},
+							critical: {
+								agents: "<?php echo __('Critical agents'); ?>",
+								modules: "<?php echo __('Critical modules'); ?>",
+								none: "<?php echo __('Critical'); ?>"
+							},
+							warning: {
+								agents: "<?php echo __('Warning agents'); ?>",
+								modules: "<?php echo __('Warning modules'); ?>",
+								none: "<?php echo __('Warning'); ?>"
+							},
+							unknown: {
+								agents: "<?php echo __('Unknown agents'); ?>",
+								modules: "<?php echo __('Unknown modules'); ?>",
+								none: "<?php echo __('Unknown'); ?>"
+							},
+							not_init: {
+								agents: "<?php echo __('Not init agents'); ?>",
+								modules: "<?php echo __('Not init modules'); ?>",
+								none: "<?php echo __('Not init'); ?>"
+							},
+							ok: {
+								agents: "<?php echo __('Normal agents'); ?>",
+								modules: "<?php echo __('Normal modules'); ?>",
+								none: "<?php echo __('Normal'); ?>"
+							}
+						}
+					});
+				}
+			},
+			dataType: "json"
+		});
+	}
+	
+	// Show the modal window of an module
+	var moduleDetailsWindow = $("<div></div>");
+	moduleDetailsWindow
+		.hide()
+		.prop("id", "module_details_window")
+		.appendTo('body');
+	
+	function show_module_detail_dialog(module_id, id_agent, server_name, offset, period, module_name) {
+		var params = {};
+		var f = new Date();
+		period = $('#period').val();
+		
+		params.selection_mode = $('input[name=selection_mode]:checked').val();
+		if (!params.selection_mode) {
+			params.selection_mode='fromnow';
+		}
+		
+		params.date_from = $('#text-date_from').val();
+		if (!params.date_from) {
+			params.date_from = f.getFullYear() + "/" + (f.getMonth() +1) + "/" + f.getDate();
+		}
+		
+		params.time_from = $('#text-time_from').val();
+		if (!params.time_from) {
+			params.time_from = f.getHours() + ":"  + f.getMinutes();
+		}
+		
+		params.date_to = $('#text-date_to').val();
+		if (!params.date_to) {
+			params.date_to =f.getFullYear() + "/" + (f.getMonth() +1) + "/" + f.getDate();
+		}
+		
+		params.time_to = $('#text-time_to').val();
+		if (!params.time_to) {
+			params.time_to = f.getHours() + ":"  + f.getMinutes();
+		}
+		
+		params.page = "include/ajax/module";
+		params.get_module_detail = 1;
+		params.server_name = server_name;
+		params.id_agent = id_agent;
+		params.id_module = module_id;
+		params.offset = offset;
+		params.period = period;
+		title =   <?php echo "'" . __("Module: ") . "'" ?> ;
+		$.ajax({
+			type: "POST",
+			url: "<?php echo ui_get_full_url('ajax.php', false, false, false); ?>",
+			data: params,
+			dataType: "html",
+			success: function(data) {
+				$("#module_details_window").hide ()
+					.empty ()
+					.append (data)
+					.dialog ({
+						resizable: true,
+						draggable: true,
+						modal: true,
+						title: title + module_name,
+						overlay: {
+							opacity: 0.5,
+							background: "black"
+						},
+						width: 650,
+						height: 500
+					})
+					.show ();
+					refresh_pagination_callback(module_id, id_agent, server_name, module_name);
+					datetime_picker_callback();
+					forced_title_callback();
+			}
+		});
+	}
+	
+	function datetime_picker_callback() {
+		$("#text-time_from, #text-time_to").timepicker({
+			showSecond: true,
+			timeFormat: '<?php echo TIME_FORMAT_JS; ?>',
+			timeOnlyTitle: '<?php echo __('Choose time');?>',
+			timeText: '<?php echo __('Time');?>',
+			hourText: '<?php echo __('Hour');?>',
+			minuteText: '<?php echo __('Minute');?>',
+			secondText: '<?php echo __('Second');?>',
+			currentText: '<?php echo __('Now');?>',
+			closeText: '<?php echo __('Close');?>'});
+		
+		$.datepicker.setDefaults($.datepicker.regional[ "<?php echo get_user_language(); ?>"]);
+		$("#text-date_from, #text-date_to").datepicker({dateFormat: "<?php echo DATE_FORMAT_JS; ?>"});
+		
+	}
+	
+	function refresh_pagination_callback (module_id, id_agent, server_name,module_name) {
+		
+		$(".binary_dialog").click( function() {
+			
+			var classes = $(this).attr('class');
+			classes = classes.split(' ');
+			var offset_class = classes[2];
+			offset_class = offset_class.split('_');
+			var offset = offset_class[1];
+			
+			var period = $('#period').val();
+			
+			show_module_detail_dialog(module_id, id_agent, server_name, offset, period,module_name);
+			return false;
+		});
+	}
+	
 </script>