diff --git a/pandora_console/general/logon_ok.php b/pandora_console/general/logon_ok.php index 6567347999..059443eff6 100644 --- a/pandora_console/general/logon_ok.php +++ b/pandora_console/general/logon_ok.php @@ -26,6 +26,12 @@ * ============================================================================ */ +use PandoraFMS\TacticalView\GeneralTacticalView; + +$tacticalView = new GeneralTacticalView(); +$tacticalView->render(); +return; +// Temporal return for develop. // Config functions. require_once 'include/config.php'; diff --git a/pandora_console/images/status_check@svg.svg b/pandora_console/images/status_check@svg.svg new file mode 100644 index 0000000000..78e62ea848 --- /dev/null +++ b/pandora_console/images/status_check@svg.svg @@ -0,0 +1,26 @@ + + + AE320C3A-79E4-4E24-956A-B81125ACFA52@svg + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pandora_console/images/status_error@svg.svg b/pandora_console/images/status_error@svg.svg new file mode 100644 index 0000000000..e6502bff7e --- /dev/null +++ b/pandora_console/images/status_error@svg.svg @@ -0,0 +1,26 @@ + + + CD9D3D2F-E199-427F-BC6C-532C8382EE45@svg + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pandora_console/include/graphs/fgraph.php b/pandora_console/include/graphs/fgraph.php index 494ec9c010..f0980836b6 100644 --- a/pandora_console/include/graphs/fgraph.php +++ b/pandora_console/include/graphs/fgraph.php @@ -1019,7 +1019,9 @@ function get_build_setup_charts($type, $options, $data) ) { $scales = $chart->options()->getScales(); - if ($options['scales']['x'] !== false) { + if (isset($options['scales']['x']) === true + && $options['scales']['x'] !== false + ) { // Defaults scalesFont X. $scalesXFonts = $scales->getX()->ticks()->getFonts(); $scalesXFonts->setFamily((empty($config['fontpath']) === true) ? 'lato' : $config['fontpath']); @@ -1028,7 +1030,9 @@ function get_build_setup_charts($type, $options, $data) $scalesXFonts->setSize(((int) $config['font_size'] + 2)); } - if ($options['scales']['y'] !== false) { + if (isset($options['scales']['y']) === true + && $options['scales']['y'] !== false + ) { // Defaults scalesFont Y. $scalesYFonts = $scales->getY()->ticks()->getFonts(); $scalesYFonts->setFamily((empty($config['fontpath']) === true) ? 'lato' : $config['fontpath']); @@ -1037,7 +1041,9 @@ function get_build_setup_charts($type, $options, $data) $scalesYFonts->setSize(((int) $config['font_size'] + 2)); } - if ($options['scales']['r'] !== false) { + if (isset($options['scales']['r']) === true + && $options['scales']['r'] !== false + ) { // Defaults scalesFont R. $scalesRFonts = $scales->getR()->pointLabels()->getFonts(); $scalesRFonts->setStyle('normal'); @@ -1053,6 +1059,10 @@ function get_build_setup_charts($type, $options, $data) $scales->getX()->setBounds($options['scales']['x']['bounds']); } + if (isset($options['scales']['x']['display']) === true) { + $scales->getX()->setDisplay($options['scales']['x']['display']); + } + if (isset($options['scales']['x']['grid']) === true && empty($options['scales']['x']['grid']) === false && is_array($options['scales']['x']['grid']) === true @@ -1098,6 +1108,10 @@ function get_build_setup_charts($type, $options, $data) $scales->getY()->setBounds($options['scales']['y']['bounds']); } + if (isset($options['scales']['y']['display']) === true) { + $scales->getY()->setDisplay($options['scales']['y']['display']); + } + if (isset($options['scales']['y']['grid']) === true && empty($options['scales']['y']['grid']) === false && is_array($options['scales']['y']['grid']) === true diff --git a/pandora_console/include/lib/TacticalView/Element.php b/pandora_console/include/lib/TacticalView/Element.php new file mode 100644 index 0000000000..a97502e0e1 --- /dev/null +++ b/pandora_console/include/lib/TacticalView/Element.php @@ -0,0 +1,56 @@ +interval = 0; + $this->title = __('Default element'); + } + + +} diff --git a/pandora_console/include/lib/TacticalView/GeneralTacticalView.php b/pandora_console/include/lib/TacticalView/GeneralTacticalView.php new file mode 100644 index 0000000000..82b042cf7c --- /dev/null +++ b/pandora_console/include/lib/TacticalView/GeneralTacticalView.php @@ -0,0 +1,115 @@ +elements = $this->instanceElements(); + } + + + /** + * Instantiate all the elements that will build the dashboard + * + * @return array + */ + public function instanceElements():array + { + global $config; + $dir = $config['homedir'].'/include/lib/TacticalView/elements/'; + + $handle = opendir($dir); + if ($handle === false) { + return []; + } + + $ignores = [ + '.', + '..', + ]; + + $elements = []; + while (false !== ($file = readdir($handle))) { + try { + if (in_array($file, $ignores) === true) { + continue; + } + + $filepath = realpath($dir.'/'.$file); + if (is_readable($filepath) === false + || is_dir($filepath) === true + || preg_match('/.*\.php$/', $filepath) === false + ) { + continue; + } + + $className = preg_replace('/.php/', '', $file); + include_once $filepath; + if (class_exists($className) === true) { + $instance = new $className(); + $elements[$className] = $instance; + } + } catch (Exception $e) { + } + } + + return $elements; + } + + + /** + * Render funcion for print the html. + * + * @return void + */ + public function render():void + { + View::render( + 'tacticalView/view', + $this->elements + ); + } + + +} diff --git a/pandora_console/include/lib/TacticalView/elements/MonitoringElements.php b/pandora_console/include/lib/TacticalView/elements/MonitoringElements.php new file mode 100644 index 0000000000..4731d54b27 --- /dev/null +++ b/pandora_console/include/lib/TacticalView/elements/MonitoringElements.php @@ -0,0 +1,41 @@ +title = __('Monitoring elements'); + } + + +} diff --git a/pandora_console/include/lib/TacticalView/elements/NewsBoard.php b/pandora_console/include/lib/TacticalView/elements/NewsBoard.php new file mode 100644 index 0000000000..4f7820b19c --- /dev/null +++ b/pandora_console/include/lib/TacticalView/elements/NewsBoard.php @@ -0,0 +1,123 @@ +title = __('News Board'); + } + + + /** + * Returns the html of the latest news. + * + * @return string + */ + public function getNews():string + { + global $config; + $options = []; + $options['id_user'] = $config['id_user']; + $options['modal'] = false; + $options['limit'] = 7; + $news = get_news($options); + + if (!empty($news)) { + $output = '
'; + foreach ($news as $article) { + $default = false; + if ($article['text'] == '<p style="text-align: center; font-size: 13px;">Hello, congratulations, if you've arrived here you already have an operational monitoring console. Remember that our forums and online documentation are available 24x7 to get you out of any trouble. You can replace this message with a personalized one at Admin tools -> Site news.</p> ') { + $article['subject'] = __('Welcome to Pandora FMS Console'); + $default = true; + } + + $text_bbdd = io_safe_output($article['text']); + $text = html_entity_decode($text_bbdd); + + $output .= '
'; + $output .= '
'; + $output .= ''.$article['subject'].''; + $output .= ''.__('By').' '.$article['author'].' '.ui_print_timestamp($article['timestamp'], true).''; + $output .= '
'; + $output .= '
'; + + if ($default) { + $output .= '
'; + $output .= '
'; + $output .= 'img colabora con nosotros - Support'; + $output .= '
'; + + $output .= ' +

'.__('Welcome to our monitoring tool so grand,').' +
'.__('Where data insights are at your command.').' +
'.__('Sales, marketing, operations too,').' +
'.__("Customer support, we've got you.").' +

+ +

'.__('Our interface is user-friendly,').' +
'.__("Customize your dashboard, it's easy.").' +
'.__('Set up alerts and gain insights so keen,').' +
'.__("Optimize your data, like you've never seen.").' +

+ +

'.__('Unleash its power now, and join the pro league,').' +
'.__('Unlock the potential of your data to intrigue.').' +
'.__('Monitoring made simple, efficient and fun,').' +
'.__('Discover a whole new way to get things done.').' +

+ +

'.__('And take control of your IT once and for all.').'

+ + '.__('You can replace this message with a personalized one at Admin tools -> Site news.').' + '; + + $output .= '
'; + } else { + $text = str_replace('title = __('General overview'); + } + + + /** + * Return the html log size status. + * + * @return string + */ + public function getLogSizeStatus():string + { + // TODO connect to automonitorization. + $status = true; + + if ($status === true) { + $image_status = html_print_image('images/status_check@svg.svg', true); + $text = html_print_div( + [ + 'content' => __('Everything’s OK!'), + 'class' => 'status-text', + ], + true + ); + } else { + $image_status = html_print_image('images/status_error@svg.svg', true); + $text = html_print_div( + [ + 'content' => __('Something’s wrong'), + 'class' => 'status-text', + ], + true + ); + } + + $output = $image_status.$text; + + return html_print_div( + [ + 'content' => $output, + 'class' => 'flex_center margin-top-5', + ], + true + ); + + } + + + /** + * Return the html Wix server status. + * + * @return string + */ + public function getWuxServerStatus():string + { + // TODO connect to automonitorization. + $status = false; + + if ($status === true) { + $image_status = html_print_image('images/status_check@svg.svg', true); + $text = html_print_div( + [ + 'content' => __('Everything’s OK!'), + 'class' => 'status-text', + ], + true + ); + } else { + $image_status = html_print_image('images/status_error@svg.svg', true); + $text = html_print_div( + [ + 'content' => __('Something’s wrong'), + 'class' => 'status-text', + ], + true + ); + } + + $output = $image_status.$text; + + return html_print_div( + [ + 'content' => $output, + 'class' => 'flex_center margin-top-5', + ], + true + ); + + } + + + /** + * Returns the html of the used licenses. + * + * @return string + */ + public function getLicenseUsage():string + { + // TODO connect to automonitorization. + $options = [ + 'labels' => [ + 'Open Source', + 'Enterprise', + 'MaaS', + ], + 'colors' => [ + '#1C4E6B', + '#5C63A2', + '#EC7176', + ], + 'legend' => [ + 'position' => 'bottom', + 'align' => 'right', + ], + 'cutout' => 80, + ]; + $pie = ring_graph([2, 4, 6], $options); + $output = html_print_div( + [ + 'content' => $pie, + 'style' => 'margin: 0 auto; max-width: 320px', + ], + true + ); + + return $output; + } + + + /** + * Returns the html of a graph with the processed xmls + * + * @return string + */ + public function getXmlProcessed():string + { + $sql = 'SELECT + utimestamp, + DATE_FORMAT(FROM_UNIXTIME(utimestamp), "%Y-%m-%d %H:00:00") AS hour, + COUNT(*) AS xml_proccessed + FROM tagent_access + WHERE FROM_UNIXTIME(utimestamp) >= NOW() - INTERVAL 24 HOUR + GROUP BY hour + ORDER BY hour;'; + + $rows = db_process_sql($sql); + + $dates = []; + $xml_proccessed = []; + $total = 0; + foreach ($rows as $key => $raw_data) { + $dates[] = date('H:i:s', $raw_data['utimestamp']); + $xml_proccessed[] = $raw_data['xml_proccessed']; + $total += $raw_data['xml_proccessed']; + } + + $options = [ + 'labels' => $dates, + 'legend' => [ 'display' => false ], + 'tooltips' => [ 'display' => false ], + 'scales' => [ + 'y' => [ + 'grid' => ['display' => false], + 'ticks' => ['display' => false], + ], + 'x' => [ + 'grid' => ['display' => false], + 'display' => false, + ], + ], + ]; + + $data = [['data' => $xml_proccessed]]; + + $graph_area = html_print_div( + [ + 'content' => line_graph($data, $options), + 'class' => 'margin-top-5 w100p h100p', + 'style' => 'max-height: 330px;', + ], + true + ); + + $total = html_print_div( + [ + 'content' => $total, + 'class' => 'text-xl', + ], + true + ); + + $output = $total.$graph_area; + + return $output; + } + + +} diff --git a/pandora_console/include/styles/general_tactical_view.css b/pandora_console/include/styles/general_tactical_view.css new file mode 100644 index 0000000000..27c8482cd3 --- /dev/null +++ b/pandora_console/include/styles/general_tactical_view.css @@ -0,0 +1,77 @@ +.row { + display: flex; + width: 100%; +} +.col-6 { + width: 49%; + display: flex; + flex-wrap: wrap; + flex-direction: column; +} +.col-7 { + width: 58%; +} +.col-5 { + width: 41%; +} +.container { + background-color: white; + border: 1px solid #e5e9ed; + border-radius: 10px; + margin: 5px; +} +.br-l { + border-left: 1px solid #e5e9ed; +} +.br-t { + border-top: 1px solid #e5e9ed; +} +.br-r { + border-right: 1px solid #e5e9ed; +} +.br-b { + border-bottom: 1px solid #e5e9ed; +} +.title { + font-size: 18px; + color: #161628; + text-align: center; + font-weight: bold; + padding: 15px 0px; +} +.subtitle { + font-size: 13px; + color: #161628; + padding-bottom: 10px; +} +.subtitle.link { + display: flex; + flex-direction: row; + justify-content: space-between; +} +.subtitle.link a { + color: #14524f; + font-size: 13px; +} +.absolute-link::after { + content: "→"; +} +.status-text { + color: #6e7079; + font-size: 13px; + margin-left: 6px; +} +.text-xl { + font-size: 40px; + color: #6c7587; + font-weight: bold; + padding-left: 8px; + margin-bottom: 8px; + line-height: initial; +} +#news-board { + min-width: 530px; + width: 100%; + max-height: 805px; + overflow-y: auto; +} diff --git a/pandora_console/include/styles/news.css b/pandora_console/include/styles/news.css index c9e66bd462..d25bcc322f 100644 --- a/pandora_console/include/styles/news.css +++ b/pandora_console/include/styles/news.css @@ -1,7 +1,7 @@ .new-board { background-color: #ffffff; - border: 1px solid #e5e9ed; - border-radius: 4px; + border-top: 1px solid #e5e9ed; + border-bottom: 1px solid #e5e9ed; margin-bottom: 15px; } @@ -36,12 +36,12 @@ display: flex; flex-direction: row; flex-wrap: nowrap; - align-items: center; + align-items: flex-start; } .default-new > div > img { width: 100%; - max-width: 430px; + max-width: 268px; height: auto; } diff --git a/pandora_console/views/tacticalView/view.php b/pandora_console/views/tacticalView/view.php new file mode 100644 index 0000000000..63c59c2790 --- /dev/null +++ b/pandora_console/views/tacticalView/view.php @@ -0,0 +1,102 @@ +
+
+
+
+
+ title; ?> +
+
+
+
+
+
+
+ + + + getLogSizeStatus(); ?> +
+
+
+
+ + + + getWuxServerStatus(); ?> +
+
+
+
+
+ + + + getLicenseUsage(); ?> +
+
+
+
+ + getXmlProcessed(); ?> +
+
+
+
+
+
+
+
+
+ title; ?> +
+
+
+ +
+
+ +
+
+
+
+ +
+
+ +
+
+
+ +
+
+ +
+
+
+
+
+
+ title; ?> +
+ getNews(); ?> +
+
+
+ +
+ +
+ +
+ +
\ No newline at end of file