#10194 new structure for general tactical view

This commit is contained in:
Daniel Cebrian 2023-09-21 17:58:18 +02:00
parent 56cb2c3232
commit 7c201d2855
12 changed files with 826 additions and 7 deletions

View File

@ -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';

View File

@ -0,0 +1,26 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="43px" height="43px" viewBox="0 0 43 43" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>AE320C3A-79E4-4E24-956A-B81125ACFA52@svg</title>
<defs>
<linearGradient x1="50%" y1="0%" x2="100%" y2="100%" id="linearGradient-1">
<stop stop-color="#82B92E" offset="0%"></stop>
<stop stop-color="#2EB9A2" offset="100%"></stop>
</linearGradient>
<path d="M0,31.4018658 L0,11.5981342 C0,3.42952349 9.87916654,0 21.5,0 C33.1208335,0 43,3.42952349 43,11.5981342 L43,31.4018658 C43,39.5704765 33.1208335,43 21.5,43 C9.87916654,43 0,39.5704765 0,31.4018658 Z" id="path-2"></path>
</defs>
<g id="Welcome-dashboard---v1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="Pandora-FMS---Tactical-view-v4" transform="translate(-324, -276)">
<g id="General-overview" transform="translate(309, 186)">
<g id="Card-1/8" transform="translate(15, 66)">
<g id="Status-check" transform="translate(0, 24)">
<mask id="mask-3" fill="white">
<use xlink:href="#path-2"></use>
</mask>
<use id="Mask" fill="url(#linearGradient-1)" xlink:href="#path-2"></use>
<path d="M40.3336211,1.77120453 C41.5051939,0.599631653 43.4046889,0.599631653 44.5762617,1.77120453 C45.7009717,2.89591449 45.7459601,4.69147742 44.7112269,5.86985562 L44.5762617,6.01384522 L20.142225,30.447882 C19.017515,31.572592 17.2219521,31.6175804 16.0435739,30.5828472 L15.8995843,30.447882 L10.2105122,24.75881 C9.03893936,23.5872371 9.03893936,21.6877422 10.2105122,20.5161693 C11.3352222,19.3914593 13.1307851,19.3464709 14.3091633,20.3812041 L14.4531529,20.5161693 L18.021,24.084 L40.3336211,1.77120453 Z" id="Path" fill="#FFFFFF" fill-rule="nonzero" mask="url(#mask-3)"></path>
</g>
</g>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.0 KiB

View File

@ -0,0 +1,26 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="43px" height="43px" viewBox="0 0 43 43" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>CD9D3D2F-E199-427F-BC6C-532C8382EE45@svg</title>
<defs>
<linearGradient x1="100%" y1="5.25852345e-07%" x2="0%" y2="50%" id="linearGradient-1">
<stop stop-color="#F72222" offset="0%"></stop>
<stop stop-color="#E12D81" offset="100%"></stop>
</linearGradient>
<path d="M0,31.4018658 L0,11.5981342 C0,3.42952349 9.87916654,0 21.5,0 C33.1208335,0 43,3.42952349 43,11.5981342 L43,31.4018658 C43,39.5704765 33.1208335,43 21.5,43 C9.87916654,43 0,39.5704765 0,31.4018658 Z" id="path-2"></path>
</defs>
<g id="Welcome-dashboard---v1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="Pandora-FMS---Tactical-view-v4" transform="translate(-519, -276)">
<g id="General-overview" transform="translate(309, 186)">
<g id="Card-1/8" transform="translate(210, 66)">
<g id="Path" transform="translate(0, 24)">
<mask id="mask-3" fill="white">
<use xlink:href="#path-2"></use>
</mask>
<use id="Mask" fill="url(#linearGradient-1)" xlink:href="#path-2"></use>
<path d="M17.9773307,13.7437145 L18.1213203,13.8786797 L21.657,17.414 L25.1923882,13.8786797 C26.363961,12.7071068 28.263456,12.7071068 29.4350288,13.8786797 C30.5597388,15.0033896 30.6047272,16.7989525 29.569994,17.9773307 L29.4350288,18.1213203 L25.9,21.657 L29.4350288,25.1923882 C30.6066017,26.363961 30.6066017,28.263456 29.4350288,29.4350288 C28.3103189,30.5597388 26.514756,30.6047272 25.3363778,29.569994 L25.1923882,29.4350288 L21.657,25.9 L18.1213203,29.4350288 C16.9497475,30.6066017 15.0502525,30.6066017 13.8786797,29.4350288 C12.7539697,28.3103189 12.7089813,26.514756 13.7437145,25.3363778 L13.8786797,25.1923882 L17.414,21.657 L13.8786797,18.1213203 C12.7071068,16.9497475 12.7071068,15.0502525 13.8786797,13.8786797 C14.9565267,12.8008326 16.650487,12.7146048 17.8269121,13.6199964 L17.9773307,13.7437145 Z" id="Path-3" fill="#FFFFFF" fill-rule="nonzero" mask="url(#mask-3)"></path>
</g>
</g>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.3 KiB

View File

@ -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

View File

@ -0,0 +1,56 @@
<?php
/**
* Element class parent for elements
*
* @category General
* @package Pandora FMS
* @subpackage TacticalView
* @version 1.0.0
* @license See below
*
* ______ ___ _______ _______ ________
* | __ \.-----.--.--.--| |.-----.----.-----. | ___| | | __|
* | __/| _ | | _ || _ | _| _ | | ___| |__ |
* |___| |___._|__|__|_____||_____|__| |___._| |___| |__|_|__|_______|
*
* ============================================================================
* Copyright (c) 2007-2023 Artica Soluciones Tecnologicas, http://www.artica.es
* This code is NOT free software. This code is NOT licenced under GPL2 licence
* You cannnot redistribute it without written permission of copyright holder.
* ============================================================================
*/
namespace PandoraFMS\TacticalView;
/**
* Parent element for general tactical view elements
*/
class Element
{
/**
* Title of section
*
* @var string
*/
public $title;
/**
* Interval for refresh element, 0 for not refresh.
*
* @var integer
*/
protected $interval;
/**
* Constructor
*/
public function __construct()
{
$this->interval = 0;
$this->title = __('Default element');
}
}

View File

@ -0,0 +1,115 @@
<?php
/**
* General tactical view
*
* @category General
* @package Pandora FMS
* @subpackage TacticalView
* @version 1.0.0
* @license See below
*
* ______ ___ _______ _______ ________
* | __ \.-----.--.--.--| |.-----.----.-----. | ___| | | __|
* | __/| _ | | _ || _ | _| _ | | ___| |__ |
* |___| |___._|__|__|_____||_____|__| |___._| |___| |__|_|__|_______|
*
* ============================================================================
* Copyright (c) 2007-2023 Artica Soluciones Tecnologicas, http://www.artica.es
* This code is NOT free software. This code is NOT licenced under GPL2 licence
* You cannnot redistribute it without written permission of copyright holder.
* ============================================================================
*/
namespace PandoraFMS\TacticalView;
use Exception;
use PandoraFMS\View;
/**
* General tactical view
*/
class GeneralTacticalView
{
/**
* List elements instanced for show in view.
*
* @var array
*/
protected $elements;
/**
* Constructor
*/
public function __construct()
{
ui_require_css_file('general_tactical_view');
$this->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
);
}
}

View File

@ -0,0 +1,41 @@
<?php
/**
* MonitoringElements element for tactical view.
*
* @category General
* @package Pandora FMS
* @subpackage TacticalView
* @version 1.0.0
* @license See below
*
* ______ ___ _______ _______ ________
* | __ \.-----.--.--.--| |.-----.----.-----. | ___| | | __|
* | __/| _ | | _ || _ | _| _ | | ___| |__ |
* |___| |___._|__|__|_____||_____|__| |___._| |___| |__|_|__|_______|
*
* ============================================================================
* Copyright (c) 2007-2023 Artica Soluciones Tecnologicas, http://www.artica.es
* This code is NOT free software. This code is NOT licenced under GPL2 licence
* You cannnot redistribute it without written permission of copyright holder.
* ============================================================================
*/
use PandoraFMS\TacticalView\Element;
/**
* MonitoringElements, this class contain all logic for this section.
*/
class MonitoringElements extends Element
{
/**
* Constructor
*/
public function __construct()
{
$this->title = __('Monitoring elements');
}
}

View File

@ -0,0 +1,123 @@
<?php
/**
* NewsBoard element for tactical view.
*
* @category General
* @package Pandora FMS
* @subpackage TacticalView
* @version 1.0.0
* @license See below
*
* ______ ___ _______ _______ ________
* | __ \.-----.--.--.--| |.-----.----.-----. | ___| | | __|
* | __/| _ | | _ || _ | _| _ | | ___| |__ |
* |___| |___._|__|__|_____||_____|__| |___._| |___| |__|_|__|_______|
*
* ============================================================================
* Copyright (c) 2007-2023 Artica Soluciones Tecnologicas, http://www.artica.es
* This code is NOT free software. This code is NOT licenced under GPL2 licence
* You cannnot redistribute it without written permission of copyright holder.
* ============================================================================
*/
use PandoraFMS\TacticalView\Element;
/**
* NewsBoard, this class contain all logic for this section.
*/
class NewsBoard extends Element
{
/**
* Constructor
*/
public function __construct()
{
ui_require_css_file('news');
include_once 'general/news_dialog.php';
$this->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 = '<div id="news-board" class="new">';
foreach ($news as $article) {
$default = false;
if ($article['text'] == '&amp;lt;p&#x20;style=&quot;text-align:&#x20;center;&#x20;font-size:&#x20;13px;&quot;&amp;gt;Hello,&#x20;congratulations,&#x20;if&#x20;you&apos;ve&#x20;arrived&#x20;here&#x20;you&#x20;already&#x20;have&#x20;an&#x20;operational&#x20;monitoring&#x20;console.&#x20;Remember&#x20;that&#x20;our&#x20;forums&#x20;and&#x20;online&#x20;documentation&#x20;are&#x20;available&#x20;24x7&#x20;to&#x20;get&#x20;you&#x20;out&#x20;of&#x20;any&#x20;trouble.&#x20;You&#x20;can&#x20;replace&#x20;this&#x20;message&#x20;with&#x20;a&#x20;personalized&#x20;one&#x20;at&#x20;Admin&#x20;tools&#x20;-&amp;amp;gt;&#x20;Site&#x20;news.&amp;lt;/p&amp;gt;&#x20;') {
$article['subject'] = __('Welcome to Pandora FMS Console');
$default = true;
}
$text_bbdd = io_safe_output($article['text']);
$text = html_entity_decode($text_bbdd);
$output .= '<div class="new-board">';
$output .= '<div class="new-board-header">';
$output .= '<span class="new-board-title">'.$article['subject'].'</span>';
$output .= '<span class="new-board-author">'.__('By').' '.$article['author'].' '.ui_print_timestamp($article['timestamp'], true).'</span>';
$output .= '</div>';
$output .= '<div class="new content">';
if ($default) {
$output .= '<div class="default-new">';
$output .= '<div class="default-image-new">';
$output .= '<img src="./images/welcome_image.svg" alt="img colabora con nosotros - Support">';
$output .= '</div><div class="default-text-new">';
$output .= '
<p>'.__('Welcome to our monitoring tool so grand,').'
<br>'.__('Where data insights are at your command.').'
<br>'.__('Sales, marketing, operations too,').'
<br>'.__("Customer support, we've got you.").'
</p>
<p>'.__('Our interface is user-friendly,').'
<br>'.__("Customize your dashboard, it's easy.").'
<br>'.__('Set up alerts and gain insights so keen,').'
<br>'.__("Optimize your data, like you've never seen.").'
</p>
<p>'.__('Unleash its power now, and join the pro league,').'
<br>'.__('Unlock the potential of your data to intrigue.').'
<br>'.__('Monitoring made simple, efficient and fun,').'
<br>'.__('Discover a whole new way to get things done.').'
</p>
<p>'.__('And take control of your IT once and for all.').'</p>
<span>'.__('You can replace this message with a personalized one at Admin tools -> Site news.').'</span>
';
$output .= '</div></div>';
} else {
$text = str_replace('<script', '&lt;script', $text);
$text = str_replace('</script', '&lt;/script', $text);
$output .= nl2br($text);
}
$output .= '</div></div>';
}
$output .= '</div>';
return $output;
}
}
}

View File

@ -0,0 +1,233 @@
<?php
/**
* Overview element for tactical view.
*
* @category General
* @package Pandora FMS
* @subpackage TacticalView
* @version 1.0.0
* @license See below
*
* ______ ___ _______ _______ ________
* | __ \.-----.--.--.--| |.-----.----.-----. | ___| | | __|
* | __/| _ | | _ || _ | _| _ | | ___| |__ |
* |___| |___._|__|__|_____||_____|__| |___._| |___| |__|_|__|_______|
*
* ============================================================================
* Copyright (c) 2007-2023 Artica Soluciones Tecnologicas, http://www.artica.es
* This code is NOT free software. This code is NOT licenced under GPL2 licence
* You cannnot redistribute it without written permission of copyright holder.
* ============================================================================
*/
use PandoraFMS\TacticalView\Element;
/**
* Overview, this class contain all logic for this section.
*/
class Overview extends Element
{
/**
* Constructor
*/
public function __construct()
{
$this->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' => __('Everythings OK!'),
'class' => 'status-text',
],
true
);
} else {
$image_status = html_print_image('images/status_error@svg.svg', true);
$text = html_print_div(
[
'content' => __('Somethings 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' => __('Everythings OK!'),
'class' => 'status-text',
],
true
);
} else {
$image_status = html_print_image('images/status_error@svg.svg', true);
$text = html_print_div(
[
'content' => __('Somethings 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;
}
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -0,0 +1,102 @@
<div class="row">
<div class="col-6">
<div id="general-overview">
<div class="container">
<div class="title">
<?php echo $Overview->title; ?>
</div>
<div class="content br-t">
<div class="row">
<div class="col-6">
<div class="row">
<div class="col-6">
<div class="padding10">
<span class="subtitle">
<?php echo __('Pandora FMS log size'); ?>
</span>
<?php echo $Overview->getLogSizeStatus(); ?>
</div>
</div>
<div class="col-6 br-l">
<div class="padding10">
<span class="subtitle">
<?php echo __('Wux server status'); ?>
</span>
<?php echo $Overview->getWuxServerStatus(); ?>
</div>
</div>
</div>
<div class="br-t">
<div class="padding10">
<span class="subtitle link">
<?php echo __('License usage'); ?> <a href=""><?php echo __('Info'); ?></a>
</span>
<?php echo $Overview->getLicenseUsage(); ?>
</div>
</div>
</div>
<div class="col-6 br-l relative">
<div class="subtitle link padding10 padding2">
<?php echo __('XML packets processed (last 24 hrs)'); ?> <a href=""><?php echo __('Info'); ?></a>
</div>
<?php echo $Overview->getXmlProcessed(); ?>
</div>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-7">
<div class="container">
<div class="title">
<?php echo $MonitoringElements->title; ?>
</div>
<div class="row">
<div class="col-6">
<div class="subtitle link padding10 padding2">
<?php echo __('Tags'); ?> <a href=""><?php echo __('Info'); ?></a>
</div>
</div>
<div class="col-6">
<div class="subtitle link padding10 padding2">
<?php echo __('By modules groups'); ?> <a href=""><?php echo __('Info'); ?></a>
</div>
</div>
</div>
<div class="row">
<div class="col-6">
<div class="subtitle link padding10 padding2">
<?php echo __('Status'); ?> <a href=""><?php echo __('Info'); ?></a>
</div>
</div>
<div class="col-6">
<div class="subtitle link padding10 padding2">
<?php echo __('Groups'); ?> <a href=""><?php echo __('Info'); ?></a>
</div>
</div>
</div>
</div>
</div>
<div class="col-5">
</div>
</div>
</div>
<div class="col-6">
<div class="container">
<div class="title">
<?php echo $NewsBoard->title; ?>
</div>
<?php echo $NewsBoard->getNews(); ?>
</div>
</div>
</div>
<div class="row">
</div>
<div class="row">
</div>