Merge branch 'new-vc-line-element' into 'develop'
New vc line element See merge request artica/pandorafms!2795
This commit is contained in:
commit
0cf42f2d74
|
@ -203,7 +203,7 @@ foreach ($layoutDatas as $layoutData) {
|
|||
$table->data[($i + 1)]['icon'] = html_print_image(
|
||||
'images/auto_sla_graph.png',
|
||||
true,
|
||||
['title' => __('Auto SLA Graph')]
|
||||
['title' => __('Event history graph')]
|
||||
);
|
||||
break;
|
||||
|
||||
|
|
|
@ -761,7 +761,7 @@ $buttons['consoles_list'] = [
|
|||
];
|
||||
$buttons['public_link'] = [
|
||||
'active' => false,
|
||||
'text' => '<a href="'.ui_get_full_url('operation/visual_console/public_console.php?hash='.$hash.'&id_layout='.$idVisualConsole.'&id_user='.$config['id_user']).'">'.html_print_image('images/camera_mc.png', true, ['title' => __('Show link to public Visual Console')]).'</a>',
|
||||
'text' => '<a href="'.ui_get_full_url('operation/visual_console/public_console.php?hash='.$hash.'&refr='.$refr.'&id_layout='.$idVisualConsole.'&id_user='.$config['id_user']).'">'.html_print_image('images/camera_mc.png', true, ['title' => __('Show link to public Visual Console')]).'</a>',
|
||||
];
|
||||
$buttons['data'] = [
|
||||
'active' => false,
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 528 B |
Binary file not shown.
After Width: | Height: | Size: 452 B |
Binary file not shown.
After Width: | Height: | Size: 459 B |
|
@ -160,27 +160,29 @@ if (file_exists('languages/'.$user_language.'.mo') === true) {
|
|||
<script language="javascript" type="text/javascript" src="graphs/flot/jquery.flot.axislabels.js"></script>
|
||||
<script language="javascript" type="text/javascript" src="graphs/flot/pandora.flot.js"></script>
|
||||
</head>
|
||||
<body bgcolor="#ffffff" style='background:#ffffff;'>
|
||||
<body style='background-color: <?php echo $params['backgroundColor']; ?>;'>
|
||||
<?php
|
||||
$params['only_image'] = false;
|
||||
$params['width'] = (int) $_REQUEST['viewport_width'];
|
||||
$params['menu'] = false;
|
||||
|
||||
$params_combined = json_decode($_REQUEST['data_combined'], true);
|
||||
$module_list = json_decode($_REQUEST['data_module_list'], true);
|
||||
$type_graph_pdf = $_REQUEST['type_graph_pdf'];
|
||||
|
||||
if ((isset($params['width']) === false
|
||||
|| ($params['width'] <= 0))
|
||||
) {
|
||||
$params['width'] = 650;
|
||||
if ((int) $params['landscape'] === 1) {
|
||||
$params['width'] = 850;
|
||||
}
|
||||
if ($params['vconsole'] === false) {
|
||||
$params['width'] = (int) $_REQUEST['viewport_width'];
|
||||
if ((isset($params['width']) === false
|
||||
|| ($params['width'] <= 0))
|
||||
) {
|
||||
$params['width'] = 650;
|
||||
if ((int) $params['landscape'] === 1) {
|
||||
$params['width'] = 850;
|
||||
}
|
||||
|
||||
if ($type_graph_pdf === 'slicebar') {
|
||||
$params['width'] = 150;
|
||||
$params['height'] = 70;
|
||||
if ($type_graph_pdf === 'slicebar') {
|
||||
$params['width'] = 150;
|
||||
$params['height'] = 70;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -3874,17 +3874,22 @@ function generator_chart_to_pdf($type_graph_pdf, $params, $params_combined=false
|
|||
|
||||
$width_img = 500;
|
||||
|
||||
// Set height image.
|
||||
$height_img = 170;
|
||||
$params['height'] = 170;
|
||||
if ((int) $params['landscape'] === 1) {
|
||||
$height_img = 150;
|
||||
$params['height'] = 150;
|
||||
}
|
||||
if ($params['vconsole'] === false) {
|
||||
// Set height image.
|
||||
$height_img = 170;
|
||||
$params['height'] = 170;
|
||||
if ((int) $params['landscape'] === 1) {
|
||||
$height_img = 150;
|
||||
$params['height'] = 150;
|
||||
}
|
||||
|
||||
if ($type_graph_pdf === 'slicebar') {
|
||||
$width_img = 360;
|
||||
$height_img = 70;
|
||||
if ($type_graph_pdf === 'slicebar') {
|
||||
$width_img = 360;
|
||||
$height_img = 70;
|
||||
}
|
||||
} else {
|
||||
$width_img = $params['width'];
|
||||
$height_img = $params['height'];
|
||||
}
|
||||
|
||||
$params_encode_json = urlencode(json_encode($params));
|
||||
|
|
|
@ -3904,7 +3904,7 @@ function graph_graphic_agentevents($id_agent, $width, $height, $period=0, $homeu
|
|||
* @param string homeurl
|
||||
* @param bool return or echo the result
|
||||
*/
|
||||
function graph_graphic_moduleevents($id_agent, $id_module, $width, $height, $period=0, $homeurl, $return=false)
|
||||
function graph_graphic_moduleevents($id_agent, $id_module, $width, $height, $period=0, $homeurl, $return=false, $ttl=1)
|
||||
{
|
||||
global $config;
|
||||
global $graphic_type;
|
||||
|
@ -3980,7 +3980,7 @@ function graph_graphic_moduleevents($id_agent, $id_module, $width, $height, $per
|
|||
$out = flot_slicesbar_graph(
|
||||
$data,
|
||||
$period,
|
||||
100,
|
||||
$width,
|
||||
$height,
|
||||
$full_legend,
|
||||
$colors,
|
||||
|
@ -3993,7 +3993,8 @@ function graph_graphic_moduleevents($id_agent, $id_module, $width, $height, $per
|
|||
$id_agent,
|
||||
[],
|
||||
true,
|
||||
1
|
||||
$ttl,
|
||||
true
|
||||
);
|
||||
|
||||
if ($return) {
|
||||
|
@ -4861,7 +4862,7 @@ function graph_nodata_image($width=300, $height=110, $type='area', $text='')
|
|||
// if ($text == '') {
|
||||
// $text = __('No data to show');
|
||||
// }
|
||||
$text_div = '<div class="nodata_text" style="text-align:center; padding: 30px 0; display:block; font-size:9.5pt;">'.$text.'</div>';
|
||||
$text_div = '<div class="nodata_text" style="text-align:center; padding: 30px 0; display:block; font-size:9.5pt;">'.$text.'</div>';
|
||||
|
||||
$image_div = $text_div.'<div class="nodata_container" style="background-position: top; width:40%;height:40%;background-size: contain;background-image: url(\''.$image.'\');"><div></div></div>';
|
||||
|
||||
|
|
|
@ -1685,6 +1685,8 @@ function html_print_input_number(array $settings):string
|
|||
'required',
|
||||
'pattern',
|
||||
'autocomplete',
|
||||
'min',
|
||||
'max',
|
||||
];
|
||||
|
||||
$output = '';
|
||||
|
@ -1904,10 +1906,15 @@ function html_print_input_hidden_extended(
|
|||
*
|
||||
* @return string HTML code if return parameter is true.
|
||||
*/
|
||||
function html_print_input_color($name, $value, $class=false, $return=false)
|
||||
function html_print_input_color($name, $value, $id='', $class=false, $return=false)
|
||||
{
|
||||
$attr_type = 'type="color"';
|
||||
$attr_id = 'id="color-'.htmlspecialchars($name, ENT_QUOTES).'"';
|
||||
if (empty($id) === true) {
|
||||
$attr_id = 'id="color-'.htmlspecialchars($name, ENT_QUOTES).'"';
|
||||
} else {
|
||||
$attr_id = 'id="'.$id.'"';
|
||||
}
|
||||
|
||||
$attr_name = 'name="'.htmlspecialchars($name, ENT_QUOTES).'"';
|
||||
$attr_value = 'value="'.htmlspecialchars($value, ENT_QUOTES).'"';
|
||||
$attr_class = 'class="'.($class !== false ? htmlspecialchars($class, ENT_QUOTES) : '').'"';
|
||||
|
@ -3380,6 +3387,11 @@ function html_print_input($data, $wrapper='div', $input_only=false)
|
|||
}
|
||||
}
|
||||
|
||||
if (isset($data['wrapper']) === true) {
|
||||
$output = '<'.$data['wrapper'].' id="wr_'.$data['name'].'" ';
|
||||
$output .= ' class="'.$data['input_class'].'">';
|
||||
}
|
||||
|
||||
switch ($data['type']) {
|
||||
case 'text':
|
||||
$output .= html_print_input_text(
|
||||
|
@ -3490,6 +3502,7 @@ function html_print_input($data, $wrapper='div', $input_only=false)
|
|||
$output .= html_print_input_color(
|
||||
$data['name'],
|
||||
$data['value'],
|
||||
$data['id'],
|
||||
((isset($data['class']) === true) ? $data['class'] : false),
|
||||
((isset($data['return']) === true) ? $data['return'] : false)
|
||||
);
|
||||
|
@ -3663,11 +3676,157 @@ function html_print_input($data, $wrapper='div', $input_only=false)
|
|||
$output .= html_print_input_multicheck($data);
|
||||
break;
|
||||
|
||||
case 'autocomplete_agent':
|
||||
$agent_name = '';
|
||||
if (isset($data['id_agent_hidden']) === true
|
||||
&& empty($data['id_agent_hidden']) === false
|
||||
) {
|
||||
if (is_metaconsole() === true) {
|
||||
$connection = metaconsole_get_connection_by_id(
|
||||
$data['server_id_hidden']
|
||||
);
|
||||
$agent_name = '';
|
||||
|
||||
if (metaconsole_load_external_db($connection) == NOERR) {
|
||||
$agent_name = db_get_value_filter(
|
||||
'alias',
|
||||
'tagente',
|
||||
['id_agente' => $data['id_agent_hidden']]
|
||||
);
|
||||
}
|
||||
|
||||
// Append server name.
|
||||
if (!empty($agent_name)) {
|
||||
$agent_name .= ' ('.$connection['server_name'].')';
|
||||
}
|
||||
|
||||
// Restore db connection.
|
||||
metaconsole_restore_db();
|
||||
} else {
|
||||
$agent_name = agents_get_alias($data['id_agent_hidden']);
|
||||
}
|
||||
}
|
||||
|
||||
$params = [];
|
||||
$params['return'] = $data['return'];
|
||||
$params['show_helptip'] = false;
|
||||
$params['input_name'] = $data['name'];
|
||||
$params['value'] = $agent_name;
|
||||
$params['javascript_is_function_select'] = true;
|
||||
|
||||
if (isset($data['module_input']) === true
|
||||
&& $data['module_input'] === true
|
||||
) {
|
||||
$params['selectbox_id'] = $data['module_name'];
|
||||
$params['add_none_module'] = $data['module_none'];
|
||||
}
|
||||
|
||||
$params['use_hidden_input_idagent'] = true;
|
||||
$params['hidden_input_idagent_id'] = 'hidden-'.$data['name_agent_hidden'];
|
||||
if (is_metaconsole()) {
|
||||
$params['use_input_id_server'] = true;
|
||||
$params['input_id_server_id'] = 'hidden-'.$data['name_server_hidden'];
|
||||
$params['metaconsole_enabled'] = true;
|
||||
}
|
||||
|
||||
$output .= html_print_input_hidden(
|
||||
$data['name_agent_hidden'],
|
||||
$data['id_agent_hidden'],
|
||||
$data['return']
|
||||
);
|
||||
|
||||
$output .= html_print_input_hidden(
|
||||
$data['name_server_hidden'],
|
||||
$data['server_id_hidden'],
|
||||
$data['return']
|
||||
);
|
||||
|
||||
$output .= ui_print_agent_autocomplete_input($params);
|
||||
break;
|
||||
|
||||
case 'autocomplete_module':
|
||||
// Module.
|
||||
if (($data['agent_id'] === false
|
||||
|| empty($data['agent_id']) === true)
|
||||
&& (isset($data['selected']) === false
|
||||
|| $data['selected'] === 0)
|
||||
) {
|
||||
$fields = [
|
||||
0 => __('Select an Agent first'),
|
||||
];
|
||||
} else {
|
||||
$sql = sprintf(
|
||||
'SELECT id_agente_modulo, nombre
|
||||
FROM tagente_modulo
|
||||
WHERE id_agente = %d
|
||||
AND delete_pending = 0',
|
||||
$data['agent_id']
|
||||
);
|
||||
|
||||
if (is_metaconsole() === true) {
|
||||
$connection = metaconsole_get_connection_by_id(
|
||||
$data['metaconsole_id']
|
||||
);
|
||||
|
||||
if (metaconsole_load_external_db($connection) == NOERR) {
|
||||
$modules_agent = db_get_all_rows_sql($sql);
|
||||
|
||||
if ($modules_agent === false) {
|
||||
$modules_agent = [];
|
||||
}
|
||||
}
|
||||
|
||||
// Restore db connection.
|
||||
metaconsole_restore_db();
|
||||
} else {
|
||||
$modules_agent = db_get_all_rows_sql($sql);
|
||||
}
|
||||
|
||||
$fields = [];
|
||||
if (isset($modules_agent) === true
|
||||
&& is_array($modules_agent) === true
|
||||
) {
|
||||
$fields = array_reduce(
|
||||
$modules_agent,
|
||||
function ($carry, $item) {
|
||||
$carry[$item['id_agente_modulo']] = $item['nombre'];
|
||||
return $carry;
|
||||
},
|
||||
[]
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
$output .= html_print_select(
|
||||
$fields,
|
||||
$data['name'],
|
||||
((isset($data['selected']) === true) ? $data['selected'] : ''),
|
||||
((isset($data['script']) === true) ? $data['script'] : ''),
|
||||
((isset($data['nothing']) === true) ? $data['nothing'] : ''),
|
||||
((isset($data['nothing_value']) === true) ? $data['nothing_value'] : 0),
|
||||
((isset($data['return']) === true) ? $data['return'] : false),
|
||||
((isset($data['multiple']) === true) ? $data['multiple'] : false),
|
||||
((isset($data['sort']) === true) ? $data['sort'] : true),
|
||||
((isset($data['class']) === true) ? $data['class'] : ''),
|
||||
((isset($data['disabled']) === true) ? $data['disabled'] : false),
|
||||
((isset($data['style']) === true) ? $data['style'] : false),
|
||||
((isset($data['option_style']) === true) ? $data['option_style'] : false),
|
||||
((isset($data['size']) === true) ? $data['size'] : false),
|
||||
((isset($data['modal']) === true) ? $data['modal'] : false),
|
||||
((isset($data['message']) === true) ? $data['message'] : ''),
|
||||
((isset($data['select_all']) === true) ? $data['select_all'] : false)
|
||||
);
|
||||
break;
|
||||
|
||||
default:
|
||||
// Ignore.
|
||||
break;
|
||||
}
|
||||
|
||||
if (isset($data['wrapper']) === true) {
|
||||
$output .= '</'.$data['wrapper'].'>';
|
||||
}
|
||||
|
||||
if ($data['label'] && $input_only === false) {
|
||||
$output .= '</'.$wrapper.'>';
|
||||
if (!$data['return']) {
|
||||
|
@ -3817,3 +3976,25 @@ function html_print_autocomplete_users_from_integria(
|
|||
echo $output;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function html_print_tabs(array $tabs)
|
||||
{
|
||||
$result = '<div id="html-tabs">';
|
||||
$result .= '<ul class="">';
|
||||
foreach ($tabs as $key => $value) {
|
||||
$result .= "<li><a href='".$value['href']."' id='".$value['id']."'>";
|
||||
$result .= html_print_image(
|
||||
'images/'.$value['img'],
|
||||
true
|
||||
);
|
||||
$result .= '<span>'.$value['name'].'</span>';
|
||||
$result .= '</a></li>';
|
||||
}
|
||||
|
||||
$result .= '</ul>';
|
||||
|
||||
$result .= '</div>';
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
|
|
@ -7919,6 +7919,7 @@ function reporting_simple_graph(
|
|||
'server_id' => $id_meta,
|
||||
'height' => $config['graph_image_height'],
|
||||
'landscape' => $content['landscape'],
|
||||
'backgroundColor' => 'transparent',
|
||||
'return_img_base_64' => true,
|
||||
];
|
||||
|
||||
|
|
|
@ -3286,7 +3286,8 @@ function visual_map_get_color_line_status($layoutData)
|
|||
/**
|
||||
* Get image of element in the visual console with status.
|
||||
*
|
||||
* @param array $layoutData The row of element in DB.
|
||||
* @param array $layoutData The row of element in DB.
|
||||
* @param boolean $status Status.
|
||||
*
|
||||
* @return string The image with the relative path to pandora console directory.
|
||||
*/
|
||||
|
@ -3294,8 +3295,12 @@ function visual_map_get_image_status_element($layoutData, $status=false)
|
|||
{
|
||||
$img = 'images/console/icons/'.$layoutData['image'];
|
||||
|
||||
if (empty($layoutData['image'])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($layoutData['type'] == 5) {
|
||||
// ICON ELEMENT
|
||||
// ICON ELEMENT.
|
||||
$img .= '.png';
|
||||
} else {
|
||||
if ($status === false) {
|
||||
|
@ -3304,35 +3309,36 @@ function visual_map_get_image_status_element($layoutData, $status=false)
|
|||
|
||||
switch ($status) {
|
||||
case 1:
|
||||
// Critical (BAD)
|
||||
// Critical (BAD).
|
||||
$img .= '_bad.png';
|
||||
break;
|
||||
|
||||
case 4:
|
||||
// Critical (ALERT)
|
||||
// Critical (ALERT).
|
||||
$img = '4'.$img.'_bad.png';
|
||||
break;
|
||||
|
||||
case 0:
|
||||
// Normal (OK)
|
||||
// Normal (OK).
|
||||
$img .= '_ok.png';
|
||||
break;
|
||||
|
||||
case 2:
|
||||
// Warning
|
||||
// Warning.
|
||||
$img .= '_warning.png';
|
||||
break;
|
||||
|
||||
case 10:
|
||||
// Warning (ALERT)
|
||||
// Warning (ALERT).
|
||||
$img = '4'.$img.'_warning.png';
|
||||
break;
|
||||
|
||||
case 3:
|
||||
// Unknown
|
||||
// Unknown.
|
||||
default:
|
||||
$img .= '.png';
|
||||
// Default is Grey (Other)
|
||||
// Default is Grey (Other).
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4260,7 +4266,7 @@ function visual_map_create_internal_name_item($label=null, $type, $image, $agent
|
|||
|
||||
case 'auto_sla_graph':
|
||||
case AUTO_SLA_GRAPH:
|
||||
$text = __('Auto SLA Graph');
|
||||
$text = __('Event history graph');
|
||||
break;
|
||||
|
||||
case 'percentile_bar':
|
||||
|
|
|
@ -56,7 +56,7 @@ function visual_map_editor_print_item_palette($visualConsole_id, $background)
|
|||
'static_graph' => __('Static Graph'),
|
||||
'percentile_item' => __('Percentile Item'),
|
||||
'module_graph' => __('Graph'),
|
||||
'auto_sla_graph' => __('Auto SLA Graph'),
|
||||
'auto_sla_graph' => __('Event history graph'),
|
||||
'simple_value' => __('Simple value').ui_print_help_tip(
|
||||
__(
|
||||
"To use 'label'field, you should write
|
||||
|
@ -738,13 +738,13 @@ function visual_map_editor_print_item_palette($visualConsole_id, $background)
|
|||
$form_items['color_cloud_def_color_row'] = [];
|
||||
$form_items['color_cloud_def_color_row']['items'] = ['color_cloud'];
|
||||
$form_items['color_cloud_def_color_row']['html'] = '<td align="left">'.__('Default color').'</td>
|
||||
<td align="left">'.html_print_input_color('default_color', $default_color, false, true).'</td>';
|
||||
<td align="left">'.html_print_input_color('default_color', $default_color, '', false, true).'</td>';
|
||||
|
||||
// Color ranges
|
||||
$color_range_tip = __('The color of the element will be the one selected in the first range created in which the value of the module is found (with the initial and final values of the range included)').'.';
|
||||
$form_items['color_cloud_color_ranges_row'] = [];
|
||||
$form_items['color_cloud_color_ranges_row']['items'] = ['color_cloud'];
|
||||
$form_items['color_cloud_color_ranges_row']['html'] = '<td align="left">'.__('Ranges').ui_print_help_tip($color_range_tip, true).'</td>'.'<td align="left">'.'<table id="new-color-range" class="databox color-range color-range-creation">'.'<tr>'.'<td>'.__('From value').'</td>'.'<td>'.html_print_input_text('from_value_new', '', '', 5, 255, true).'</td>'.'<td rowspan="4">'.'<a class="color-range-add" href="#">'.html_print_image('images/add.png', true).'</a>'.'</td>'.'</tr>'.'<td>'.__('To value').'</td>'.'<td>'.html_print_input_text('to_value_new', '', '', 5, 255, true).'</td>'.'<td></td>'.'<tr>'.'</tr>'.'<tr>'.'<td>'.__('Color').'</td>'.'<td>'.html_print_input_color('color_new', $default_color, false, true).'</td>'.'<td></td>'.'</tr>'.'</table>'.'</td>';
|
||||
$form_items['color_cloud_color_ranges_row']['html'] = '<td align="left">'.__('Ranges').ui_print_help_tip($color_range_tip, true).'</td>'.'<td align="left">'.'<table id="new-color-range" class="databox color-range color-range-creation">'.'<tr>'.'<td>'.__('From value').'</td>'.'<td>'.html_print_input_text('from_value_new', '', '', 5, 255, true).'</td>'.'<td rowspan="4">'.'<a class="color-range-add" href="#">'.html_print_image('images/add.png', true).'</a>'.'</td>'.'</tr>'.'<td>'.__('To value').'</td>'.'<td>'.html_print_input_text('to_value_new', '', '', 5, 255, true).'</td>'.'<td></td>'.'<tr>'.'</tr>'.'<tr>'.'<td>'.__('Color').'</td>'.'<td>'.html_print_input_color('color_new', $default_color, '', false, true).'</td>'.'<td></td>'.'</tr>'.'</table>'.'</td>';
|
||||
|
||||
// End of Color Cloud rows
|
||||
$form_items['show_on_top_row'] = [];
|
||||
|
@ -1299,7 +1299,7 @@ function visual_map_editor_print_toolbox()
|
|||
visual_map_print_button_editor('module_graph', __('Module Graph'), 'left', false, 'graph_min', true);
|
||||
visual_map_print_button_editor('donut_graph', __('Serialized pie graph'), 'left', false, 'donut_graph_min', true);
|
||||
visual_map_print_button_editor('bars_graph', __('Bars Graph'), 'left', false, 'bars_graph_min', true);
|
||||
visual_map_print_button_editor('auto_sla_graph', __('Auto SLA Graph'), 'left', false, 'auto_sla_graph_min', true);
|
||||
visual_map_print_button_editor('auto_sla_graph', __('Event history graph'), 'left', false, 'auto_sla_graph_min', true);
|
||||
visual_map_print_button_editor('simple_value', __('Simple Value'), 'left', false, 'binary_min', true);
|
||||
visual_map_print_button_editor('label', __('Label'), 'left', false, 'label_min', true);
|
||||
visual_map_print_button_editor('icon', __('Icon'), 'left', false, 'icon_min', true);
|
||||
|
|
|
@ -168,7 +168,8 @@ function vbar_graph(
|
|||
$backgroundColor='white',
|
||||
$from_ux=false,
|
||||
$from_wux=false,
|
||||
$tick_color='white'
|
||||
$tick_color='white',
|
||||
$base64=false
|
||||
) {
|
||||
setup_watermark($water_mark, $water_mark_file, $water_mark_url);
|
||||
|
||||
|
@ -178,22 +179,23 @@ function vbar_graph(
|
|||
|
||||
if ($ttl == 2) {
|
||||
$params = [
|
||||
'chart_data' => $chart_data,
|
||||
'width' => $width,
|
||||
'height' => $height,
|
||||
'color' => $color,
|
||||
'legend' => $legend,
|
||||
'long_index' => $long_index,
|
||||
'homeurl' => $homeurl,
|
||||
'unit' => $unit,
|
||||
'water_mark_url' => $water_mark_url,
|
||||
'homedir' => $homedir,
|
||||
'font' => $font,
|
||||
'font_size' => $font_size,
|
||||
'from_ux' => $from_ux,
|
||||
'from_wux' => $from_wux,
|
||||
'backgroundColor' => $backgroundColor,
|
||||
'tick_color' => $tick_color,
|
||||
'chart_data' => $chart_data,
|
||||
'width' => $width,
|
||||
'height' => $height,
|
||||
'color' => $color,
|
||||
'legend' => $legend,
|
||||
'long_index' => $long_index,
|
||||
'homeurl' => $homeurl,
|
||||
'unit' => $unit,
|
||||
'water_mark_url' => $water_mark_url,
|
||||
'homedir' => $homedir,
|
||||
'font' => $font,
|
||||
'font_size' => $font_size,
|
||||
'from_ux' => $from_ux,
|
||||
'from_wux' => $from_wux,
|
||||
'backgroundColor' => $backgroundColor,
|
||||
'tick_color' => $tick_color,
|
||||
'return_img_base_64' => $base64,
|
||||
];
|
||||
return generator_chart_to_pdf('vbar', $params);
|
||||
}
|
||||
|
@ -345,26 +347,28 @@ function hbar_graph(
|
|||
$backgroundColor='white',
|
||||
$tick_color='white',
|
||||
$val_min=null,
|
||||
$val_max=null
|
||||
$val_max=null,
|
||||
$base64=false
|
||||
) {
|
||||
setup_watermark($water_mark, $water_mark_file, $water_mark_url);
|
||||
|
||||
if (empty($chart_data)) {
|
||||
if ($chart_data === false || empty($chart_data) === true) {
|
||||
return graph_nodata_image($width, $height, 'hbar');
|
||||
}
|
||||
|
||||
if ($ttl == 2) {
|
||||
$params = [
|
||||
'chart_data' => $chart_data,
|
||||
'width' => $width,
|
||||
'height' => $height,
|
||||
'water_mark_url' => $water_mark_url,
|
||||
'font' => $font,
|
||||
'font_size' => $font_size,
|
||||
'backgroundColor' => $backgroundColor,
|
||||
'tick_color' => $tick_color,
|
||||
'val_min' => $val_min,
|
||||
'val_max' => $val_max,
|
||||
'chart_data' => $chart_data,
|
||||
'width' => $width,
|
||||
'height' => $height,
|
||||
'water_mark_url' => $water_mark_url,
|
||||
'font' => $font,
|
||||
'font_size' => $font_size,
|
||||
'backgroundColor' => $backgroundColor,
|
||||
'tick_color' => $tick_color,
|
||||
'val_min' => $val_min,
|
||||
'val_max' => $val_max,
|
||||
'return_img_base_64' => $base64,
|
||||
];
|
||||
return generator_chart_to_pdf('hbar', $params);
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* global $ */
|
||||
/* exported pandoraFlotPie, pandoraFlotPieCustom */
|
||||
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
function pandoraFlotPie(
|
||||
graph_id,
|
||||
values,
|
||||
|
@ -73,8 +73,9 @@ function pandoraFlotPie(
|
|||
case "right":
|
||||
case "inner":
|
||||
conf_pie.legend.container = $("#" + graph_id + "_legend");
|
||||
break;
|
||||
default:
|
||||
//TODO FOR TOP OR LEFT OR RIGHT
|
||||
// TODO FOR TOP OR LEFT OR RIGHT.
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -85,7 +86,7 @@ function pandoraFlotPie(
|
|||
|
||||
// Events
|
||||
$("#" + graph_id).bind("plothover", pieHover);
|
||||
$("#" + graph_id).bind("plotclick", pieClick);
|
||||
//$("#" + graph_id).bind("plotclick", pieClick);
|
||||
$("#" + graph_id).bind("mouseout", resetInteractivity);
|
||||
$("#" + graph_id).css("margin-left", "auto");
|
||||
$("#" + graph_id).css("margin-right", "auto");
|
||||
|
@ -125,6 +126,7 @@ function pandoraFlotPie(
|
|||
}
|
||||
}
|
||||
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
function pandoraFlotPieCustom(
|
||||
graph_id,
|
||||
values,
|
||||
|
@ -311,11 +313,11 @@ function pandoraFlotPieCustom(
|
|||
}
|
||||
}
|
||||
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
function pandoraFlotHBars(
|
||||
graph_id,
|
||||
values,
|
||||
labels,
|
||||
water_mark,
|
||||
maxvalue,
|
||||
water_mark,
|
||||
separator,
|
||||
|
@ -346,7 +348,7 @@ function pandoraFlotHBars(
|
|||
var serie = values[i].split(separator);
|
||||
|
||||
var aux = new Array();
|
||||
for (j = 0; j < serie.length; j++) {
|
||||
for (var j = 0; j < serie.length; j++) {
|
||||
var aux2 = parseFloat(serie[j]);
|
||||
aux.push([aux2, j]);
|
||||
datas.push({
|
||||
|
@ -358,16 +360,10 @@ function pandoraFlotHBars(
|
|||
|
||||
var labels_total = new Array();
|
||||
labels = labels.split(separator);
|
||||
i = 0;
|
||||
for (i = 0; i < labels.length; i++) {
|
||||
for (var i = 0; i < labels.length; i++) {
|
||||
labels_total.push([i, labels[i]]);
|
||||
}
|
||||
|
||||
var stack = 0,
|
||||
bars = true,
|
||||
lines = false,
|
||||
steps = false;
|
||||
var k = 0;
|
||||
var options = {
|
||||
series: {
|
||||
bars: {
|
||||
|
@ -428,15 +424,14 @@ function pandoraFlotHBars(
|
|||
$("#" + graph_id).HUseTooltip();
|
||||
$("#" + graph_id).css("margin-left", "auto");
|
||||
$("#" + graph_id).css("margin-right", "auto");
|
||||
//~ $('#' + graph_id).find('div.legend-tooltip').tooltip({ track: true });
|
||||
|
||||
function yFormatter(v, axis) {
|
||||
format = new Array();
|
||||
for (i = 0; i < labels_total.length; i++) {
|
||||
// v, axis;
|
||||
function yFormatter() {
|
||||
var format = new Array();
|
||||
for (var i = 0; i < labels_total.length; i++) {
|
||||
var label = labels_total[i][1];
|
||||
// var shortLabel = reduceText(label, 25);
|
||||
var title = label;
|
||||
var margin_top = 0;
|
||||
if (label.length > 30) {
|
||||
label = reduceText(label, 30);
|
||||
}
|
||||
|
@ -460,9 +455,10 @@ function pandoraFlotHBars(
|
|||
return format;
|
||||
}
|
||||
|
||||
function xFormatter(v, axis) {
|
||||
label = parseFloat(v);
|
||||
text = label.toLocaleString();
|
||||
// v, axis;
|
||||
function xFormatter(v) {
|
||||
var label = parseFloat(v);
|
||||
var text = label.toLocaleString();
|
||||
if (label >= 1000000) text = text.substring(0, 4) + "M";
|
||||
else if (label >= 100000) text = text.substring(0, 3) + "K";
|
||||
else if (label >= 1000) text = text.substring(0, 2) + "K";
|
||||
|
@ -500,7 +496,7 @@ $.fn.HUseTooltip = function() {
|
|||
$("#tooltip").remove();
|
||||
|
||||
var x = item.datapoint[0];
|
||||
var y = item.datapoint[1];
|
||||
// var y = item.datapoint[1];
|
||||
|
||||
var color = item.series.color;
|
||||
showTooltip(pos.pageX, pos.pageY, color, "<strong>" + x + "</strong>");
|
||||
|
@ -523,7 +519,7 @@ $.fn.VUseTooltip = function() {
|
|||
|
||||
$("#tooltip").remove();
|
||||
|
||||
var x = item.datapoint[0];
|
||||
// var x = item.datapoint[0];
|
||||
var y = item.datapoint[1];
|
||||
|
||||
var color = item.series.color;
|
||||
|
@ -555,6 +551,7 @@ function showTooltip(x, y, color, contents) {
|
|||
.fadeIn(200);
|
||||
}
|
||||
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
function pandoraFlotVBars(
|
||||
graph_id,
|
||||
values,
|
||||
|
@ -562,7 +559,6 @@ function pandoraFlotVBars(
|
|||
labels_long,
|
||||
legend,
|
||||
colors,
|
||||
water_mark,
|
||||
maxvalue,
|
||||
water_mark,
|
||||
separator,
|
||||
|
@ -590,11 +586,11 @@ function pandoraFlotVBars(
|
|||
: ["#FFA631", "#e63c52", "#f3b200", "#5BB6E5", "#F2919D", "#82b92e"];
|
||||
var datas = new Array();
|
||||
|
||||
for (i = 0; i < values.length; i++) {
|
||||
for (var i = 0; i < values.length; i++) {
|
||||
var serie = values[i].split(separator);
|
||||
|
||||
var aux = new Array();
|
||||
for (j = 0; j < serie.length; j++) {
|
||||
for (var j = 0; j < serie.length; j++) {
|
||||
var aux2 = parseFloat(serie[j]);
|
||||
aux.push([aux2, j]);
|
||||
if (from_ux) {
|
||||
|
@ -618,11 +614,6 @@ function pandoraFlotVBars(
|
|||
labels_total.push([i, labels[i]]);
|
||||
}
|
||||
|
||||
var stack = 0,
|
||||
bars = true,
|
||||
lines = false,
|
||||
steps = false;
|
||||
|
||||
var options = {
|
||||
series: {
|
||||
bars: {
|
||||
|
@ -650,9 +641,9 @@ function pandoraFlotVBars(
|
|||
axisLabelFontFamily: font + "Font",
|
||||
axisLabelPadding: 100,
|
||||
autoscaleMargin: 0.02,
|
||||
tickFormatter: function(v, axis) {
|
||||
label = parseFloat(v);
|
||||
text = label.toLocaleString();
|
||||
tickFormatter: function(v) {
|
||||
var label = parseFloat(v);
|
||||
var text = label.toLocaleString();
|
||||
if (label >= 1000000) text = text.substring(0, 4) + "M";
|
||||
else if (label >= 100000) text = text.substring(0, 3) + "K";
|
||||
else if (label >= 1000) text = text.substring(0, 2) + "K";
|
||||
|
@ -718,7 +709,7 @@ function pandoraFlotVBars(
|
|||
.css("top", "+0px")
|
||||
.css("left", "-20px");
|
||||
// Format functions
|
||||
function xFormatter(v, axis) {
|
||||
function xFormatter() {
|
||||
var format = new Array();
|
||||
for (i = 0; i < labels_total.length; i++) {
|
||||
var label = labels_total[i][1];
|
||||
|
@ -751,7 +742,8 @@ function pandoraFlotVBars(
|
|||
return format;
|
||||
}
|
||||
|
||||
function yFormatter(v, axis) {
|
||||
/*
|
||||
function yFormatter(v) {
|
||||
return (
|
||||
'<div class="' +
|
||||
font +
|
||||
|
@ -768,6 +760,7 @@ function pandoraFlotVBars(
|
|||
'<div style="font-size:' + font_size + 'pt !important;">' + v + "</div>"
|
||||
);
|
||||
}
|
||||
*/
|
||||
|
||||
if (water_mark) {
|
||||
set_watermark(
|
||||
|
@ -778,6 +771,7 @@ function pandoraFlotVBars(
|
|||
}
|
||||
}
|
||||
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
function pandoraFlotSlicebar(
|
||||
graph_id,
|
||||
values,
|
||||
|
@ -802,9 +796,9 @@ function pandoraFlotSlicebar(
|
|||
full_legend = full_legend.split(separator);
|
||||
}
|
||||
|
||||
var font_size = parseInt(font_size);
|
||||
font_size = parseInt(font_size);
|
||||
if (font != undefined)
|
||||
var font = font
|
||||
font = font
|
||||
.split("/")
|
||||
.pop()
|
||||
.split(".")
|
||||
|
@ -884,7 +878,7 @@ function pandoraFlotSlicebar(
|
|||
|
||||
$.plot($("#" + graph_id), datas, options);
|
||||
|
||||
if (match == null) {
|
||||
if (match == null && not_interactive == 0) {
|
||||
// Events
|
||||
$("#" + graph_id).bind("plothover", function(event, pos, item) {
|
||||
if (item) {
|
||||
|
@ -919,6 +913,8 @@ function pandoraFlotSlicebar(
|
|||
//current date
|
||||
var dateObj = new Date();
|
||||
|
||||
var newdate = "";
|
||||
var newdate2 = "";
|
||||
if (full_legend != "") {
|
||||
newdate = full_legend[item.seriesIndex];
|
||||
newdate2 = full_legend[item.seriesIndex + 1];
|
||||
|
@ -968,8 +964,8 @@ function pandoraFlotSlicebar(
|
|||
}
|
||||
|
||||
// Format functions
|
||||
function xFormatter(v, axis) {
|
||||
d = new Date(1000 * (v + datelimit));
|
||||
function xFormatter(v) {
|
||||
var d = new Date(1000 * (v + datelimit));
|
||||
var monthNames = [
|
||||
"Jan",
|
||||
"Feb",
|
||||
|
@ -1000,6 +996,7 @@ function pandoraFlotSlicebar(
|
|||
}
|
||||
}
|
||||
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
function pandoraFlotArea(
|
||||
graph_id,
|
||||
values,
|
||||
|
@ -1036,7 +1033,7 @@ function pandoraFlotArea(
|
|||
var legend_color = params.legend_color;
|
||||
var update_legend = {};
|
||||
var force_integer = 0;
|
||||
var title = params.title;
|
||||
// var title = params.title;
|
||||
var divisor = params.divisor;
|
||||
|
||||
if (typeof divisor === "undefined") {
|
||||
|
|
|
@ -462,7 +462,8 @@ function d3_donut_graph($id, $width, $height, $module_data, $resume_color)
|
|||
$recipient_name = 'donut_graph_'.$id;
|
||||
$recipient_name_to_js = '#donut_graph_'.$id;
|
||||
|
||||
$output = '<div id='.$recipient_name." style='overflow: hidden;'></div>";
|
||||
$output = '';
|
||||
$output .= '<div id='.$recipient_name." style='overflow: hidden;'></div>";
|
||||
$output .= include_javascript_d3(true);
|
||||
$output .= '<style type="text/css">
|
||||
path {
|
||||
|
@ -472,6 +473,7 @@ function d3_donut_graph($id, $width, $height, $module_data, $resume_color)
|
|||
</style>';
|
||||
|
||||
$output .= "<script language=\"javascript\" type=\"text/javascript\">
|
||||
$('".$recipient_name_to_js."').empty();
|
||||
print_donut_graph('".$recipient_name_to_js."', ".$width.', '.$height.', '.$module_data.", '".$resume_color."');
|
||||
</script>";
|
||||
|
||||
|
|
|
@ -143,7 +143,7 @@ function flot_area_graph(
|
|||
// Parent layer.
|
||||
$return = "<div class='parent_graph' style='width: ".($params['width']).';'.$background_style.$padding_vconsole."'>";
|
||||
|
||||
if (empty($params['title']) === false) {
|
||||
if ($params['title'] === true && empty($params['title']) === false) {
|
||||
$return .= '<p style="text-align:center;">'.$params['title'].'</p>';
|
||||
}
|
||||
|
||||
|
@ -279,12 +279,6 @@ function flot_area_graph(
|
|||
// Trick to get translated string from javascript.
|
||||
$return .= html_print_input_hidden('unknown_text', __('Unknown'), true);
|
||||
|
||||
// To use the js document ready event or not. Default true.
|
||||
$document_ready = true;
|
||||
if (isset($params['document_ready']) === true) {
|
||||
$document_ready = $params['document_ready'];
|
||||
}
|
||||
|
||||
$values = json_encode($array_data);
|
||||
|
||||
$legend = json_encode($legend);
|
||||
|
@ -302,10 +296,6 @@ function flot_area_graph(
|
|||
|
||||
$return .= "<script type='text/javascript'>";
|
||||
|
||||
if ($document_ready === true) {
|
||||
$return .= '$(document).ready( function () {';
|
||||
}
|
||||
|
||||
$return .= "pandoraFlotArea(\n";
|
||||
$return .= "'".$graph_id."', \n";
|
||||
$return .= $values.", \n";
|
||||
|
@ -319,10 +309,6 @@ function flot_area_graph(
|
|||
$return .= $array_events_alerts."\n";
|
||||
$return .= ');';
|
||||
|
||||
if ($document_ready === true) {
|
||||
$return .= '});';
|
||||
}
|
||||
|
||||
$return .= '</script>';
|
||||
|
||||
// Parent layer.
|
||||
|
@ -629,8 +615,7 @@ function flot_hcolumn_chart($graph_data, $width, $height, $water_mark, $font='',
|
|||
|
||||
// Javascript code
|
||||
$return .= "<script type='text/javascript'>";
|
||||
$return .= "pandoraFlotHBars('$graph_id', '$values', '$labels',
|
||||
false, $max, '$water_mark', '$separator', '$separator2', '$font', $font_size, '$background_color', '$tick_color', $val_min, $val_max)";
|
||||
$return .= "pandoraFlotHBars('$graph_id', '$values', '$labels', $max, '$water_mark', '$separator', '$separator2', '$font', $font_size, '$background_color', '$tick_color', $val_min, $val_max)";
|
||||
$return .= '</script>';
|
||||
|
||||
return $return;
|
||||
|
@ -722,12 +707,12 @@ function flot_vcolumn_chart($graph_data, $width, $height, $color, $legend, $long
|
|||
$return .= "<script type='text/javascript'>";
|
||||
if ($from_ux) {
|
||||
if ($from_wux) {
|
||||
$return .= "pandoraFlotVBars('$graph_id', '$values', '$labels', '$labels', '$legend', '$colors', false, $max, '$water_mark', '$separator', '$separator2','$font',$font_size, true, true, '$background_color', '$tick_color')";
|
||||
$return .= "pandoraFlotVBars('$graph_id', '$values', '$labels', '$labels', '$legend', '$colors', $max, '$water_mark', '$separator', '$separator2','$font',$font_size, true, true, '$background_color', '$tick_color')";
|
||||
} else {
|
||||
$return .= "pandoraFlotVBars('$graph_id', '$values', '$labels', '$labels', '$legend', '$colors', false, $max, '$water_mark', '$separator', '$separator2','$font',$font_size, true, false, '$background_color', '$tick_color')";
|
||||
$return .= "pandoraFlotVBars('$graph_id', '$values', '$labels', '$labels', '$legend', '$colors', $max, '$water_mark', '$separator', '$separator2','$font',$font_size, true, false, '$background_color', '$tick_color')";
|
||||
}
|
||||
} else {
|
||||
$return .= "pandoraFlotVBars('$graph_id', '$values', '$labels', '$labels', '$legend', '$colors', false, $max, '$water_mark', '$separator', '$separator2','$font',$font_size, false, false, '$background_color', '$tick_color')";
|
||||
$return .= "pandoraFlotVBars('$graph_id', '$values', '$labels', '$labels', '$legend', '$colors', $max, '$water_mark', '$separator', '$separator2','$font',$font_size, false, false, '$background_color', '$tick_color')";
|
||||
}
|
||||
|
||||
$return .= '</script>';
|
||||
|
@ -791,15 +776,17 @@ function flot_slicesbar_graph(
|
|||
// Get a unique identifier to graph
|
||||
$graph_id = uniqid('graph_');
|
||||
|
||||
$height = ((int) $height + 15);
|
||||
|
||||
// Set some containers to legend, graph, timestamp tooltip, etc.
|
||||
if ($stat_win) {
|
||||
$height = ((int) $height + 15);
|
||||
$return = "<div id='$graph_id' class='noresizevc graph $adapt_key' style='width: ".$width.'%; height: '.$height."px; display: inline-block;'></div>";
|
||||
} else {
|
||||
if ($widgets) {
|
||||
$width = ((int) $width - 10);
|
||||
$height = ((int) $height - 10);
|
||||
$return = "<div id='$graph_id' class='noresizevc graph $adapt_key' style='width: ".$width.'px; height: '.$height."px;'></div>";
|
||||
} else {
|
||||
$height = ((int) $height + 15);
|
||||
$return = "<div id='$graph_id' class='noresizevc graph $adapt_key' style='width: ".$width.'%; height: '.$height."px;'></div>";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,6 +12,8 @@
|
|||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
/* globals jQuery, d3 */
|
||||
|
||||
// The recipient is the selector of the html element
|
||||
// The elements is an array with the names of the wheel elements
|
||||
// The matrix must be a 2 dimensional array with a row and a column for each element
|
||||
|
@ -2293,6 +2295,7 @@ function print_interior_circular_progress_bar(
|
|||
})();
|
||||
}
|
||||
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
function print_donut_graph(
|
||||
recipient,
|
||||
width,
|
||||
|
@ -2309,40 +2312,13 @@ function print_donut_graph(
|
|||
|
||||
svg.append("g").attr("class", "slices");
|
||||
|
||||
var radius = 120;
|
||||
var increment_y = 60;
|
||||
var increment_y_padding = 25;
|
||||
var decrement_x_padding = 150;
|
||||
if (width >= 500) {
|
||||
radius = 180;
|
||||
increment_y = 60;
|
||||
increment_y_padding = 20;
|
||||
decrement_x_padding = 40;
|
||||
} else if (width >= 400) {
|
||||
radius = 140;
|
||||
increment_y = 40;
|
||||
increment_y_padding = 20;
|
||||
decrement_x_padding = 40;
|
||||
} else if (width >= 300) {
|
||||
radius = 100;
|
||||
increment_y = 40;
|
||||
increment_y_padding = 15;
|
||||
decrement_x_padding = 40;
|
||||
} else if (width >= 200) {
|
||||
radius = 50;
|
||||
increment_y = 40;
|
||||
increment_y_padding = 15;
|
||||
decrement_x_padding = 25;
|
||||
} else if (width >= 100) {
|
||||
radius = 20;
|
||||
increment_y = 20;
|
||||
increment_y_padding = 8;
|
||||
decrement_x_padding = 25;
|
||||
} else {
|
||||
radius = 10;
|
||||
increment_y = 10;
|
||||
increment_y_padding = 3;
|
||||
decrement_x_padding = 5;
|
||||
var heightLegend = 25 * module_data.length;
|
||||
|
||||
var maxRadius = (height - heightLegend) / 2;
|
||||
|
||||
var radius = maxRadius;
|
||||
if (maxRadius > width / 2) {
|
||||
radius = width / 2;
|
||||
}
|
||||
|
||||
var arc = d3.svg
|
||||
|
@ -2365,37 +2341,22 @@ function print_donut_graph(
|
|||
svg
|
||||
.append("g")
|
||||
.append("rect")
|
||||
.attr(
|
||||
"transform",
|
||||
"translate(" +
|
||||
(width / 2 - (radius + decrement_x_padding)) +
|
||||
"," +
|
||||
(height / 2 - radius - increment_y) +
|
||||
")"
|
||||
)
|
||||
.attr("fill", m_d.color)
|
||||
.attr("x", -20)
|
||||
.attr("y", -10)
|
||||
.attr("width", 20)
|
||||
.attr("height", 10);
|
||||
.attr("x", 20)
|
||||
.attr("y", 20 * (key + 1))
|
||||
.attr("width", 25)
|
||||
.attr("height", 15);
|
||||
|
||||
svg
|
||||
.append("g")
|
||||
.append("text")
|
||||
.attr("fill", resume_color)
|
||||
.attr(
|
||||
"transform",
|
||||
"translate(" +
|
||||
(width / 2 - (radius + decrement_x_padding) + 10) +
|
||||
"," +
|
||||
(height / 2 - radius - increment_y) +
|
||||
")"
|
||||
)
|
||||
.attr("transform", "translate(" + 40 + "," + 20 * (key + 1) + ")")
|
||||
.attr("x", 15)
|
||||
.attr("y", 10)
|
||||
.text(m_d.tag_name)
|
||||
.style("font-family", "smallfontFont")
|
||||
.style("font-size", "7pt");
|
||||
|
||||
increment_y -= increment_y_padding;
|
||||
});
|
||||
|
||||
function donutData() {
|
||||
|
@ -2425,7 +2386,7 @@ function print_donut_graph(
|
|||
.attr("class", "slice")
|
||||
.attr(
|
||||
"transform",
|
||||
"translate(" + width / 2 + "," + (height - radius) + ")"
|
||||
"translate(" + width / 2 + "," + (height + heightLegend) / 2 + ")"
|
||||
);
|
||||
|
||||
slice
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* global $ */
|
||||
/* global $ uniqId*/
|
||||
/* exported load_modal */
|
||||
/*JS to Show user modals :
|
||||
- Confirm dialogs.
|
||||
|
@ -60,12 +60,19 @@ function logo_preview(icon_name, icon_path, incoming_options) {
|
|||
}
|
||||
|
||||
// Advanced Form control.
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
function load_modal(settings) {
|
||||
var AJAX_RUNNING = 0;
|
||||
var data = new FormData();
|
||||
if (settings.extradata) {
|
||||
settings.extradata.forEach(function(item) {
|
||||
if (item.value != undefined) data.append(item.name, item.value);
|
||||
if (item.value != undefined) {
|
||||
if (item.value instanceof Object || item.value instanceof Array) {
|
||||
data.append(item.name, JSON.stringify(item.value));
|
||||
} else {
|
||||
data.append(item.name, item.value);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
data.append("page", settings.onshow.page);
|
||||
|
@ -99,6 +106,10 @@ function load_modal(settings) {
|
|||
};
|
||||
}
|
||||
|
||||
if (settings.beforeClose == undefined) {
|
||||
settings.beforeClose = function() {};
|
||||
}
|
||||
|
||||
settings.target.html("Loading modal...");
|
||||
settings.target
|
||||
.dialog({
|
||||
|
@ -168,7 +179,6 @@ function load_modal(settings) {
|
|||
text: settings.modal.ok,
|
||||
click: function() {
|
||||
if (AJAX_RUNNING) return;
|
||||
|
||||
if (settings.onsubmit != undefined) {
|
||||
if (settings.onsubmit.preaction != undefined) {
|
||||
settings.onsubmit.preaction();
|
||||
|
@ -189,56 +199,83 @@ function load_modal(settings) {
|
|||
formdata.append("method", settings.onsubmit.method);
|
||||
|
||||
var flagError = false;
|
||||
if (Array.isArray(settings.form) === false) {
|
||||
$("#" + settings.form + " :input").each(function() {
|
||||
if (this.checkValidity() === false) {
|
||||
$(this).attr("title", this.validationMessage);
|
||||
$(this).tooltip({
|
||||
tooltipClass: "uitooltip",
|
||||
position: {
|
||||
my: "right bottom",
|
||||
at: "right top",
|
||||
using: function(position, feedback) {
|
||||
$(this).css(position);
|
||||
$("<div>")
|
||||
.addClass("arrow")
|
||||
.addClass(feedback.vertical)
|
||||
.addClass(feedback.horizontal)
|
||||
.appendTo(this);
|
||||
}
|
||||
}
|
||||
});
|
||||
$(this).tooltip("open");
|
||||
|
||||
$("#" + settings.form + " :input").each(function() {
|
||||
if (this.checkValidity() === false) {
|
||||
$(this).attr("title", this.validationMessage);
|
||||
$(this).tooltip({
|
||||
tooltipClass: "uitooltip",
|
||||
position: {
|
||||
my: "right bottom",
|
||||
at: "right top",
|
||||
using: function(position, feedback) {
|
||||
$(this).css(position);
|
||||
$("<div>")
|
||||
.addClass("arrow")
|
||||
.addClass(feedback.vertical)
|
||||
.addClass(feedback.horizontal)
|
||||
.appendTo(this);
|
||||
var element = $(this);
|
||||
setTimeout(
|
||||
function(element) {
|
||||
element.tooltip("destroy");
|
||||
element.removeAttr("title");
|
||||
},
|
||||
3000,
|
||||
element
|
||||
);
|
||||
|
||||
flagError = true;
|
||||
}
|
||||
|
||||
if (this.type == "file") {
|
||||
if ($(this).prop("files")[0]) {
|
||||
formdata.append(this.name, $(this).prop("files")[0]);
|
||||
}
|
||||
} else {
|
||||
if ($(this).attr("type") == "checkbox") {
|
||||
if (this.checked) {
|
||||
formdata.append(this.name, "on");
|
||||
}
|
||||
} else {
|
||||
formdata.append(this.name, $(this).val());
|
||||
}
|
||||
}
|
||||
});
|
||||
} else {
|
||||
settings.form.forEach(function(element) {
|
||||
$("#" + element + " :input").each(function() {
|
||||
// TODO VALIDATE ALL INPUTS.
|
||||
if (this.type == "file") {
|
||||
if ($(this).prop("files")[0]) {
|
||||
formdata.append(this.name, $(this).prop("files")[0]);
|
||||
}
|
||||
} else {
|
||||
if ($(this).attr("type") == "checkbox") {
|
||||
if (this.checked) {
|
||||
formdata.append(this.name, "on");
|
||||
}
|
||||
} else {
|
||||
formdata.append(this.name, $(this).val());
|
||||
}
|
||||
}
|
||||
});
|
||||
$(this).tooltip("open");
|
||||
|
||||
var element = $(this);
|
||||
setTimeout(
|
||||
function(element) {
|
||||
element.tooltip("destroy");
|
||||
element.removeAttr("title");
|
||||
},
|
||||
3000,
|
||||
element
|
||||
);
|
||||
|
||||
flagError = true;
|
||||
}
|
||||
|
||||
if (this.type == "file") {
|
||||
if ($(this).prop("files")[0]) {
|
||||
formdata.append(this.name, $(this).prop("files")[0]);
|
||||
}
|
||||
} else {
|
||||
if ($(this).attr("type") == "checkbox") {
|
||||
if (this.checked) {
|
||||
formdata.append(this.name, "on");
|
||||
}
|
||||
} else {
|
||||
formdata.append(this.name, $(this).val());
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
if (flagError === false) {
|
||||
if (
|
||||
settings.onsubmitClose != undefined &&
|
||||
settings.onsubmitClose == 1
|
||||
) {
|
||||
$(this).dialog("close");
|
||||
}
|
||||
|
||||
$.ajax({
|
||||
method: "post",
|
||||
url: settings.url,
|
||||
|
@ -289,17 +326,32 @@ function load_modal(settings) {
|
|||
modal: true,
|
||||
title: settings.modal.title,
|
||||
width: width,
|
||||
minHeight:
|
||||
settings.onshow.minHeight != undefined
|
||||
? settings.onshow.minHeight
|
||||
: "auto",
|
||||
maxHeight:
|
||||
settings.onshow.maxHeight != undefined
|
||||
? settings.onshow.maxHeight
|
||||
: "auto",
|
||||
overlay: settings.modal.overlay,
|
||||
buttons: required_buttons,
|
||||
closeOnEscape: false,
|
||||
closeOnEscape: true,
|
||||
open: function() {
|
||||
$(".ui-dialog-titlebar-close").hide();
|
||||
//$(".ui-dialog-titlebar-close").hide();
|
||||
},
|
||||
close: function() {
|
||||
if (id_modal_target != undefined) {
|
||||
$(id_modal_target).remove();
|
||||
}
|
||||
}
|
||||
|
||||
if (settings.cleanup != undefined) {
|
||||
settings.cleanup();
|
||||
}
|
||||
|
||||
$(this).dialog("destroy");
|
||||
},
|
||||
beforeClose: settings.beforeClose()
|
||||
});
|
||||
},
|
||||
error: function(data) {
|
||||
|
@ -308,7 +360,9 @@ function load_modal(settings) {
|
|||
});
|
||||
}
|
||||
|
||||
//Function that shows a dialog box to confirm closures of generic manners. The modal id is random
|
||||
// Function that shows a dialog box to confirm closures of generic manners.
|
||||
// The modal id is random.
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
function confirmDialog(settings) {
|
||||
var randomStr = uniqId();
|
||||
|
||||
|
@ -365,6 +419,7 @@ function confirmDialog(settings) {
|
|||
*
|
||||
* @return {void}
|
||||
*/
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
function generalShowMsg(data, idMsg) {
|
||||
var title = data.title[data.error];
|
||||
var text = data.text[data.error];
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -2,6 +2,7 @@
|
|||
|
||||
global $config;
|
||||
|
||||
|
||||
if (!is_ajax()) {
|
||||
return;
|
||||
}
|
||||
|
@ -9,57 +10,329 @@ if (!is_ajax()) {
|
|||
require_once $config['homedir'].'/vendor/autoload.php';
|
||||
|
||||
use Models\VisualConsole\Container as VisualConsole;
|
||||
use Models\VisualConsole\View as Viewer;
|
||||
use Models\VisualConsole\Item as Item;
|
||||
|
||||
$method = get_parameter('method');
|
||||
if ($method) {
|
||||
$viewer = new Viewer();
|
||||
try {
|
||||
if (method_exists($viewer, $method) === true) {
|
||||
echo $viewer->{$method}();
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
echo json_encode(['error' => $e->getMessage()]);
|
||||
return;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$visualConsoleId = (int) get_parameter('visualConsoleId');
|
||||
$getVisualConsole = (bool) get_parameter('getVisualConsole');
|
||||
$getVisualConsoleItems = (bool) get_parameter('getVisualConsoleItems');
|
||||
$updateVisualConsoleItem = (bool) get_parameter('updateVisualConsoleItem');
|
||||
$createVisualConsoleItem = (bool) get_parameter('createVisualConsoleItem');
|
||||
$getVisualConsoleItem = (bool) get_parameter('getVisualConsoleItem');
|
||||
$removeVisualConsoleItem = (bool) get_parameter('removeVisualConsoleItem');
|
||||
$copyVisualConsoleItem = (bool) get_parameter('copyVisualConsoleItem');
|
||||
$getImagesVisualConsole = (bool) get_parameter('getImagesVisualConsole');
|
||||
$createColorRangeVisualConsole = (bool) get_parameter(
|
||||
'createColorRangeVisualConsole'
|
||||
);
|
||||
$getTimeZoneVisualConsole = (bool) get_parameter('getTimeZoneVisualConsole');
|
||||
$serviceListVisualConsole = (bool) get_parameter(
|
||||
'serviceListVisualConsole'
|
||||
);
|
||||
|
||||
// Check groups can access user.
|
||||
$aclUserGroups = [];
|
||||
if (!users_can_manage_group_all('AR')) {
|
||||
$aclUserGroups = array_keys(users_get_groups(false, 'AR'));
|
||||
}
|
||||
$loadtabs = (bool) get_parameter('loadtabs');
|
||||
|
||||
ob_clean();
|
||||
|
||||
if ($getVisualConsole === true) {
|
||||
if ($visualConsoleId) {
|
||||
// Retrieve the visual console.
|
||||
$visualConsole = VisualConsole::fromDB(['id' => $visualConsoleId]);
|
||||
$visualConsoleData = $visualConsole->toArray();
|
||||
$groupId = $visualConsoleData['groupId'];
|
||||
$vcGroupId = $visualConsoleData['groupId'];
|
||||
|
||||
// ACL.
|
||||
$aclRead = check_acl($config['id_user'], $groupId, 'VR');
|
||||
$aclWrite = check_acl($config['id_user'], $groupId, 'VW');
|
||||
$aclManage = check_acl($config['id_user'], $groupId, 'VM');
|
||||
$aclRead = check_acl($config['id_user'], $vcGroupId, 'VR');
|
||||
$aclWrite = check_acl($config['id_user'], $vcGroupId, 'VW');
|
||||
$aclManage = check_acl($config['id_user'], $vcGroupId, 'VM');
|
||||
|
||||
if (!$aclRead && !$aclWrite && !$aclManage) {
|
||||
db_pandora_audit(
|
||||
'ACL Violation',
|
||||
'Trying to access visual console without group access'
|
||||
);
|
||||
exit;
|
||||
http_response_code(403);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if ($getVisualConsole === true) {
|
||||
echo $visualConsole;
|
||||
return;
|
||||
} else if ($getVisualConsoleItems === true) {
|
||||
// Check groups can access user.
|
||||
$aclUserGroups = [];
|
||||
if (!users_can_manage_group_all('AR')) {
|
||||
$aclUserGroups = array_keys(users_get_groups(false, 'AR'));
|
||||
}
|
||||
|
||||
echo $visualConsole;
|
||||
} else if ($getVisualConsoleItems === true) {
|
||||
$vcItems = VisualConsole::getItemsFromDB($visualConsoleId, $aclUserGroups);
|
||||
echo '['.implode($vcItems, ',').']';
|
||||
} else if ($updateVisualConsoleItem === true) {
|
||||
$visualConsoleId = (integer) get_parameter('visualConsoleId');
|
||||
$visualConsoleItemId = (integer) get_parameter('visualConsoleItemId');
|
||||
return;
|
||||
} else if ($getVisualConsoleItem === true
|
||||
|| $updateVisualConsoleItem === true
|
||||
) {
|
||||
$itemId = (int) get_parameter('visualConsoleItemId');
|
||||
|
||||
try {
|
||||
$item = VisualConsole::getItemFromDB($itemId);
|
||||
} catch (Throwable $e) {
|
||||
// Bad params.
|
||||
http_response_code(400);
|
||||
return;
|
||||
}
|
||||
|
||||
$itemData = $item->toArray();
|
||||
$itemType = $itemData['type'];
|
||||
$itemAclGroupId = $itemData['aclGroupId'];
|
||||
|
||||
// ACL.
|
||||
$aclRead = check_acl($config['id_user'], $itemAclGroupId, 'VR');
|
||||
$aclWrite = check_acl($config['id_user'], $itemAclGroupId, 'VW');
|
||||
$aclManage = check_acl($config['id_user'], $itemAclGroupId, 'VM');
|
||||
|
||||
if (!$aclRead && !$aclWrite && !$aclManage) {
|
||||
db_pandora_audit(
|
||||
'ACL Violation',
|
||||
'Trying to access visual console without group access'
|
||||
);
|
||||
http_response_code(403);
|
||||
return;
|
||||
}
|
||||
|
||||
// Check also the group Id for the group item.
|
||||
if ($itemType === GROUP_ITEM) {
|
||||
$itemGroupId = $itemData['groupId'];
|
||||
// ACL.
|
||||
$aclRead = check_acl($config['id_user'], $itemGroupId, 'VR');
|
||||
$aclWrite = check_acl($config['id_user'], $itemGroupId, 'VW');
|
||||
$aclManage = check_acl($config['id_user'], $itemGroupId, 'VM');
|
||||
|
||||
if (!$aclRead && !$aclWrite && !$aclManage) {
|
||||
db_pandora_audit(
|
||||
'ACL Violation',
|
||||
'Trying to access visual console without group access'
|
||||
);
|
||||
http_response_code(403);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if ($getVisualConsoleItem === true) {
|
||||
echo $item;
|
||||
return;
|
||||
} else if ($updateVisualConsoleItem === true) {
|
||||
$data = get_parameter('data');
|
||||
|
||||
if (isset($data) === true) {
|
||||
$data['id'] = $itemId;
|
||||
$data['id_layout'] = $visualConsoleId;
|
||||
$result = $item->save($data);
|
||||
|
||||
echo $item;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
} else if ($createVisualConsoleItem === true) {
|
||||
// TODO: ACL.
|
||||
$data = get_parameter('data');
|
||||
if ($data) {
|
||||
// Inserted data in new item.
|
||||
$class = VisualConsole::getItemClass((int) $data['type']);
|
||||
try {
|
||||
// Save the new item.
|
||||
$data['id_layout'] = $visualConsoleId;
|
||||
$result = $class::save($data);
|
||||
} catch (\Throwable $th) {
|
||||
// There is no item in the database.
|
||||
echo false;
|
||||
return;
|
||||
}
|
||||
|
||||
$class = VisualConsole::getItemClass($data['type']);
|
||||
// Extract data new item inserted.
|
||||
try {
|
||||
$item = VisualConsole::getItemFromDB($result);
|
||||
} catch (Throwable $e) {
|
||||
// Bad params.
|
||||
http_response_code(400);
|
||||
return;
|
||||
}
|
||||
|
||||
$item_data = [];
|
||||
$item_data['id'] = $visualConsoleItemId;
|
||||
$item_data['id_layout'] = $visualConsoleId;
|
||||
echo $item;
|
||||
} else {
|
||||
echo false;
|
||||
}
|
||||
|
||||
$item = $class::fromDB($item_data);
|
||||
$result = $item->save($data);
|
||||
return;
|
||||
} else if ($removeVisualConsoleItem === true) {
|
||||
$itemId = (int) get_parameter('visualConsoleItemId');
|
||||
|
||||
echo json_encode($result);
|
||||
try {
|
||||
$item = VisualConsole::getItemFromDB($itemId);
|
||||
} catch (\Throwable $th) {
|
||||
// There is no item in the database.
|
||||
http_response_code(404);
|
||||
return;
|
||||
}
|
||||
|
||||
$itemData = $item->toArray();
|
||||
$itemAclGroupId = $itemData['aclGroupId'];
|
||||
|
||||
$aclWrite = check_acl($config['id_user'], $itemAclGroupId, 'VW');
|
||||
$aclManage = check_acl($config['id_user'], $itemAclGroupId, 'VM');
|
||||
|
||||
// ACL.
|
||||
if (!$aclWrite && !$aclManage) {
|
||||
db_pandora_audit(
|
||||
'ACL Violation',
|
||||
'Trying to delete visual console item without group access'
|
||||
);
|
||||
http_response_code(403);
|
||||
return;
|
||||
}
|
||||
|
||||
$data = get_parameter('data');
|
||||
$result = $item::delete($itemId);
|
||||
echo $result;
|
||||
return;
|
||||
} else if ($copyVisualConsoleItem === true) {
|
||||
$itemId = (int) get_parameter('visualConsoleItemId');
|
||||
|
||||
// Get a copy of the item.
|
||||
$item = VisualConsole::getItemFromDB($itemId);
|
||||
$data = $item->toArray();
|
||||
$data['id_layout'] = $visualConsoleId;
|
||||
if ($data['type'] === LINE_ITEM) {
|
||||
$data['endX'] = ($data['endX'] + 20);
|
||||
$data['endY'] = ($data['endY'] + 20);
|
||||
$data['startX'] = ($data['startX'] + 20);
|
||||
$data['startY'] = ($data['startY'] + 20);
|
||||
} else {
|
||||
$data['x'] = ($data['x'] + 20);
|
||||
$data['y'] = ($data['y'] + 20);
|
||||
}
|
||||
|
||||
unset($data['id']);
|
||||
|
||||
$class = VisualConsole::getItemClass((int) $data['type']);
|
||||
try {
|
||||
// Save the new item.
|
||||
$result = $class::save($data);
|
||||
} catch (\Throwable $th) {
|
||||
// There is no item in the database.
|
||||
echo false;
|
||||
return;
|
||||
}
|
||||
|
||||
echo $result;
|
||||
return;
|
||||
} else if ($getImagesVisualConsole) {
|
||||
$img = get_parameter('nameImg', 'appliance');
|
||||
$only = (bool) get_parameter('only', 0);
|
||||
$count = Item::imagesElementsVC($img, $only);
|
||||
echo json_encode($count);
|
||||
return;
|
||||
} else if ($createColorRangeVisualConsole) {
|
||||
$uniqId = \uniqid();
|
||||
$baseUrl = ui_get_full_url('/', false, false, false);
|
||||
$from = get_parameter('from', 0);
|
||||
$to = get_parameter('to', 0);
|
||||
$color = get_parameter('color', 0);
|
||||
|
||||
$rangeFrom = [
|
||||
'name' => 'rangeFrom[]',
|
||||
'type' => 'number',
|
||||
'value' => $from,
|
||||
'return' => true,
|
||||
];
|
||||
|
||||
$rangeTo = [
|
||||
'name' => 'rangeTo[]',
|
||||
'type' => 'number',
|
||||
'value' => $to,
|
||||
'return' => true,
|
||||
];
|
||||
|
||||
$rangeColor = [
|
||||
'wrapper' => 'div',
|
||||
'name' => 'rangeColor[]',
|
||||
'type' => 'color',
|
||||
'value' => $color,
|
||||
'return' => true,
|
||||
];
|
||||
|
||||
$removeBtn = [
|
||||
'name' => 'Remove',
|
||||
'label' => '',
|
||||
'type' => 'button',
|
||||
'attributes' => 'class="remove-item-img"',
|
||||
'return' => true,
|
||||
'script' => 'removeColorRange(\''.$uniqId.'\')',
|
||||
];
|
||||
|
||||
$classRangeColor = 'interval-color-ranges flex-row flex-start w100p';
|
||||
$liRangeColor = '<li id="li-'.$uniqId.'" class="'.$classRangeColor.'">';
|
||||
$liRangeColor .= '<label>'.__('From').'</label>';
|
||||
$liRangeColor .= html_print_input($rangeFrom);
|
||||
$liRangeColor .= '<label>'.__('To').'</label>';
|
||||
$liRangeColor .= html_print_input($rangeTo);
|
||||
$liRangeColor .= '<label>'.__('Color').'</label>';
|
||||
$liRangeColor .= '<div>';
|
||||
$liRangeColor .= html_print_input($rangeColor);
|
||||
$liRangeColor .= '</div>';
|
||||
$liRangeColor .= '<label></label>';
|
||||
$liRangeColor .= html_print_input($removeBtn);
|
||||
$liRangeColor .= '<li>';
|
||||
|
||||
echo $liRangeColor;
|
||||
return;
|
||||
} else if ($getTimeZoneVisualConsole) {
|
||||
$zone = get_parameter('zone', 'Europe');
|
||||
$zones = Item::zonesVC($zone);
|
||||
echo json_encode($zones);
|
||||
return;
|
||||
} else if ($serviceListVisualConsole) {
|
||||
if (!enterprise_installed()) {
|
||||
echo json_encode(false);
|
||||
return;
|
||||
}
|
||||
|
||||
enterprise_include_once('include/functions_services.php');
|
||||
// Services list.
|
||||
$services = [];
|
||||
$services = enterprise_hook(
|
||||
'services_get_services',
|
||||
[
|
||||
false,
|
||||
[
|
||||
'id',
|
||||
'name',
|
||||
],
|
||||
]
|
||||
);
|
||||
|
||||
echo io_safe_output(json_encode($services));
|
||||
return;
|
||||
} else if ($loadtabs) {
|
||||
$viewer = new Viewer();
|
||||
echo $viewer->loadForm();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
exit;
|
||||
|
|
|
@ -76,6 +76,7 @@ abstract class CachedModel extends Model
|
|||
{
|
||||
global $config;
|
||||
|
||||
// TODO: Remove references to the VC items. This class should be usable with any resource.
|
||||
if ($filter['cache_expiration'] > 0) {
|
||||
// Obtain the item's data from cache.
|
||||
$cachedData = static::fetchCachedData($filter);
|
||||
|
|
|
@ -71,6 +71,18 @@ abstract class Model
|
|||
abstract public function save(array $data=[]);
|
||||
|
||||
|
||||
/**
|
||||
* Delete an item in the database
|
||||
*
|
||||
* @param integer $itemId Identifier of the Item.
|
||||
*
|
||||
* @return boolean The modeled element data structure stored into the DB.
|
||||
*
|
||||
* @abstract
|
||||
*/
|
||||
abstract public function delete(int $itemId): bool;
|
||||
|
||||
|
||||
/**
|
||||
* Constructor of the model. It won't be public. The instances
|
||||
* will be created through factories which start with from*.
|
||||
|
@ -151,7 +163,7 @@ abstract class Model
|
|||
*/
|
||||
public function toJson(): string
|
||||
{
|
||||
return \json_encode($this->data);
|
||||
return json_encode($this->data);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -123,6 +123,21 @@ final class Container extends Model
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
* Delete an item in the database
|
||||
*
|
||||
* @param integer $itemId Identifier of the Item.
|
||||
*
|
||||
* @return boolean The modeled element data structure stored into the DB.
|
||||
*
|
||||
* @overrides Model::delete.
|
||||
*/
|
||||
public function delete(int $itemId): bool
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Extract a group Id value.
|
||||
*
|
||||
|
@ -254,7 +269,7 @@ final class Container extends Model
|
|||
$backgroundImage = static::extractBackgroundImage($row);
|
||||
|
||||
if ($backgroundUrl === null && $backgroundImage !== null) {
|
||||
$row['backgroundURL'] = ui_get_full_url(
|
||||
$row['backgroundURL'] = \ui_get_full_url(
|
||||
'images/console/background/'.$backgroundImage,
|
||||
false,
|
||||
false,
|
||||
|
@ -406,4 +421,46 @@ final class Container extends Model
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
* Obtain an item which belong to the Visual Console.
|
||||
*
|
||||
* @param integer $itemId Identifier of the Item.
|
||||
*
|
||||
* @return Model Item or Line.
|
||||
* @throws \Exception When the data cannot be retrieved from the DB.
|
||||
*/
|
||||
public static function getItemFromDB(int $itemId): Model
|
||||
{
|
||||
// Default filter.
|
||||
$filter = ['id' => $itemId];
|
||||
$fields = [
|
||||
'DISTINCT(id) AS id',
|
||||
'type',
|
||||
'cache_expiration',
|
||||
'id_layout',
|
||||
];
|
||||
|
||||
$row = \db_get_row_filter(
|
||||
'tlayout_data',
|
||||
$filter,
|
||||
$fields,
|
||||
'OR'
|
||||
);
|
||||
|
||||
if ($rows === false) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$class = static::getItemClass((int) $row['type']);
|
||||
|
||||
try {
|
||||
$item = $class::fromDB($row);
|
||||
} catch (\Throwable $e) {
|
||||
// TODO: Log this?
|
||||
}
|
||||
|
||||
return $item;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -27,6 +27,73 @@ final class BarsGraph extends Item
|
|||
protected static $useHtmlOutput = true;
|
||||
|
||||
|
||||
/**
|
||||
* Extract a type graph value.
|
||||
*
|
||||
* @param array $data Unknown input data structure.
|
||||
*
|
||||
* @return string One of 'vertical' or 'horizontal'. 'vertical' by default.
|
||||
*/
|
||||
private static function getTypeGraph(array $data)
|
||||
{
|
||||
return static::notEmptyStringOr(
|
||||
static::issetInArray(
|
||||
$data,
|
||||
[
|
||||
'typeGraph',
|
||||
'type_graph',
|
||||
'graphType',
|
||||
]
|
||||
),
|
||||
null
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return a valid representation of a record in database.
|
||||
*
|
||||
* @param array $data Input data.
|
||||
*
|
||||
* @return array Data structure representing a record in database.
|
||||
*
|
||||
* @overrides Item->encode.
|
||||
*/
|
||||
protected function encode(array $data): array
|
||||
{
|
||||
$return = parent::encode($data);
|
||||
|
||||
$type_graph = static::getTypeGraph($data);
|
||||
if ($type_graph !== null) {
|
||||
$return['type_graph'] = $type_graph;
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Extract a graph type value.
|
||||
*
|
||||
* @param array $data Unknown input data structure.
|
||||
*
|
||||
* @return string 'line' or 'area'. 'line' by default.
|
||||
*/
|
||||
private static function extractGraphType(array $data): string
|
||||
{
|
||||
$value = static::issetInArray($data, ['graphType', 'type_graph']);
|
||||
|
||||
switch ($value) {
|
||||
case 'line':
|
||||
case 'area':
|
||||
return $value;
|
||||
|
||||
default:
|
||||
return 'line';
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns a valid representation of the model.
|
||||
*
|
||||
|
@ -156,14 +223,6 @@ final class BarsGraph extends Item
|
|||
$moduleId = $linkedModule['moduleId'];
|
||||
$metaconsoleId = $linkedModule['metaconsoleId'];
|
||||
|
||||
if ($agentId === null) {
|
||||
throw new \InvalidArgumentException('missing agent Id');
|
||||
}
|
||||
|
||||
if ($moduleId === null) {
|
||||
throw new \InvalidArgumentException('missing module Id');
|
||||
}
|
||||
|
||||
// Add colors that will use the graphics.
|
||||
$color = [];
|
||||
|
||||
|
@ -246,9 +305,9 @@ final class BarsGraph extends Item
|
|||
// Maybe connect to node.
|
||||
$nodeConnected = false;
|
||||
if (\is_metaconsole() === true && $metaconsoleId !== null) {
|
||||
$server = \metaconsole_get_connection_by_id($metaconsoleId);
|
||||
$nodeConnected = \metaconsole_connect(
|
||||
null,
|
||||
$metaconsoleId
|
||||
$server
|
||||
) === NOERR;
|
||||
|
||||
if ($nodeConnected === false) {
|
||||
|
@ -259,6 +318,9 @@ final class BarsGraph extends Item
|
|||
}
|
||||
|
||||
$moduleData = \get_bars_module_data($moduleId);
|
||||
if ($moduleData !== false && is_array($moduleData) === true) {
|
||||
array_pop($moduleData);
|
||||
}
|
||||
|
||||
$waterMark = [
|
||||
'file' => $config['homedir'].'/images/logo_vertical_water.png',
|
||||
|
@ -286,22 +348,20 @@ final class BarsGraph extends Item
|
|||
$color,
|
||||
[],
|
||||
[],
|
||||
\ui_get_full_url(
|
||||
'images/image_problem_area.png',
|
||||
false,
|
||||
false,
|
||||
false
|
||||
),
|
||||
'images/image_problem_area.png',
|
||||
'',
|
||||
'',
|
||||
$waterMark,
|
||||
$config['fontpath'],
|
||||
6,
|
||||
$config['fontsize'],
|
||||
'',
|
||||
0,
|
||||
2,
|
||||
$config['homeurl'],
|
||||
$backGroundColor,
|
||||
$gridColor
|
||||
$gridColor,
|
||||
null,
|
||||
null,
|
||||
true
|
||||
);
|
||||
} else {
|
||||
$graph = \vbar_graph(
|
||||
|
@ -321,14 +381,15 @@ final class BarsGraph extends Item
|
|||
'',
|
||||
$waterMark,
|
||||
$config['fontpath'],
|
||||
6,
|
||||
$config['fontsize'],
|
||||
'',
|
||||
0,
|
||||
2,
|
||||
$config['homeurl'],
|
||||
$backGroundColor,
|
||||
true,
|
||||
false,
|
||||
$gridColor
|
||||
$gridColor,
|
||||
true
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -337,10 +398,149 @@ final class BarsGraph extends Item
|
|||
\metaconsole_restore_db();
|
||||
}
|
||||
|
||||
$data['html'] = $graph;
|
||||
$imgbase64 = 'data:image/jpg;base64,';
|
||||
$imgbase64 .= $graph;
|
||||
|
||||
$data['html'] = $imgbase64;
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Generates inputs for form (specific).
|
||||
*
|
||||
* @param array $values Default values.
|
||||
*
|
||||
* @return array Of inputs.
|
||||
*
|
||||
* @throws Exception On error.
|
||||
*/
|
||||
public static function getFormInputs(array $values): array
|
||||
{
|
||||
// Default values.
|
||||
$values = static::getDefaultGeneralValues($values);
|
||||
|
||||
// Retrieve global - common inputs.
|
||||
$inputs = Item::getFormInputs($values);
|
||||
|
||||
if (is_array($inputs) !== true) {
|
||||
throw new Exception(
|
||||
'[BarsGraph]::getFormInputs parent class return is not an array'
|
||||
);
|
||||
}
|
||||
|
||||
if ($values['tabSelected'] === 'specific') {
|
||||
// Background color.
|
||||
$fields = [
|
||||
'white' => __('White'),
|
||||
'black' => __('Black'),
|
||||
'transparent' => __('Transparent'),
|
||||
];
|
||||
|
||||
$inputs[] = [
|
||||
'label' => __('Background color'),
|
||||
'arguments' => [
|
||||
'type' => 'select',
|
||||
'fields' => $fields,
|
||||
'name' => 'backgroundColor',
|
||||
'selected' => $values['backgroundColor'],
|
||||
'return' => true,
|
||||
'sort' => false,
|
||||
],
|
||||
];
|
||||
|
||||
// Graph Type.
|
||||
$fields = [
|
||||
'horizontal' => __('Horizontal'),
|
||||
'vertical' => __('Vertical'),
|
||||
];
|
||||
|
||||
$inputs[] = [
|
||||
'label' => __('Graph Type'),
|
||||
'arguments' => [
|
||||
'type' => 'select',
|
||||
'fields' => $fields,
|
||||
'name' => 'typeGraph',
|
||||
'selected' => $values['typeGraph'],
|
||||
'return' => true,
|
||||
],
|
||||
];
|
||||
|
||||
// Grid color.
|
||||
$inputs[] = [
|
||||
'label' => __('Grid color'),
|
||||
'arguments' => [
|
||||
'wrapper' => 'div',
|
||||
'name' => 'gridColor',
|
||||
'type' => 'color',
|
||||
'value' => $values['gridColor'],
|
||||
'return' => true,
|
||||
],
|
||||
];
|
||||
|
||||
// Autocomplete agents.
|
||||
$inputs[] = [
|
||||
'label' => __('Agent'),
|
||||
'arguments' => [
|
||||
'type' => 'autocomplete_agent',
|
||||
'name' => 'agentAlias',
|
||||
'id_agent_hidden' => $values['agentId'],
|
||||
'name_agent_hidden' => 'agentId',
|
||||
'server_id_hidden' => $values['metaconsoleId'],
|
||||
'name_server_hidden' => 'metaconsoleId',
|
||||
'return' => true,
|
||||
'module_input' => true,
|
||||
'module_name' => 'moduleId',
|
||||
'module_none' => false,
|
||||
],
|
||||
];
|
||||
|
||||
// Autocomplete module.
|
||||
$inputs[] = [
|
||||
'label' => __('Module'),
|
||||
'arguments' => [
|
||||
'type' => 'autocomplete_module',
|
||||
'fields' => $fields,
|
||||
'name' => 'moduleId',
|
||||
'selected' => $values['moduleId'],
|
||||
'return' => true,
|
||||
'sort' => false,
|
||||
'agent_id' => $values['agentId'],
|
||||
'metaconsole_id' => $values['metaconsoleId'],
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
return $inputs;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Default values.
|
||||
*
|
||||
* @param array $values Array values.
|
||||
*
|
||||
* @return array Array with default values.
|
||||
*
|
||||
* @overrides Item->getDefaultGeneralValues.
|
||||
*/
|
||||
public function getDefaultGeneralValues(array $values): array
|
||||
{
|
||||
// Retrieve global - common inputs.
|
||||
$values = parent::getDefaultGeneralValues($values);
|
||||
|
||||
// Default values.
|
||||
if (isset($values['width']) === false) {
|
||||
$values['width'] = 300;
|
||||
}
|
||||
|
||||
if (isset($values['height']) === false) {
|
||||
$values['height'] = 180;
|
||||
}
|
||||
|
||||
return $values;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -12,6 +12,89 @@ final class Box extends Item
|
|||
{
|
||||
|
||||
|
||||
/**
|
||||
* Extract the "Fill transparent" switch value.
|
||||
*
|
||||
* @param array $data Unknown input data structure.
|
||||
*
|
||||
* @return mixed If the statistics should be shown or not.
|
||||
*/
|
||||
private static function getFillTransparent(array $data)
|
||||
{
|
||||
return static::issetInArray(
|
||||
$data,
|
||||
[
|
||||
'fillTransparent',
|
||||
'show_statistics',
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Extract a fill color value.
|
||||
*
|
||||
* @param array $data Unknown input data structure.
|
||||
*
|
||||
* @return mixed String representing the fill color (not empty) or null.
|
||||
*/
|
||||
protected static function getFillColor(array $data)
|
||||
{
|
||||
return static::notEmptyStringOr(
|
||||
static::issetInArray(
|
||||
$data,
|
||||
[
|
||||
'fillColor',
|
||||
'fill_color',
|
||||
'labelColor',
|
||||
]
|
||||
),
|
||||
null
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return a valid representation of a record in database.
|
||||
*
|
||||
* @param array $data Input data.
|
||||
*
|
||||
* @return array Data structure representing a record in database.
|
||||
*
|
||||
* @overrides Item->encode.
|
||||
*/
|
||||
protected function encode(array $data): array
|
||||
{
|
||||
$return = parent::encode($data);
|
||||
|
||||
$border_width = parent::getBorderWidth($data);
|
||||
if ($border_width !== null) {
|
||||
if ($border_width < 1) {
|
||||
$border_width = 1;
|
||||
}
|
||||
|
||||
$return['border_width'] = $border_width;
|
||||
}
|
||||
|
||||
$border_color = static::getBorderColor($data);
|
||||
if ($border_color !== null) {
|
||||
$return['border_color'] = $border_color;
|
||||
}
|
||||
|
||||
$fill_color = static::getFillColor($data);
|
||||
if ($fill_color !== null) {
|
||||
$return['fill_color'] = $fill_color;
|
||||
}
|
||||
|
||||
$fill_transparent = static::getFillTransparent($data);
|
||||
if ($fill_transparent !== null) {
|
||||
$return['show_statistics'] = static::parseBool($fill_transparent);
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns a valid representation of the model.
|
||||
*
|
||||
|
@ -30,10 +113,26 @@ final class Box extends Item
|
|||
$boxData['borderWidth'] = $this->extractBorderWidth($data);
|
||||
$boxData['borderColor'] = $this->extractBorderColor($data);
|
||||
$boxData['fillColor'] = $this->extractFillColor($data);
|
||||
$boxData['fillTransparent'] = $this->extractFillTransparent($data);
|
||||
return $boxData;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Extract the "Fill transparent" switch value.
|
||||
*
|
||||
* @param array $data Unknown input data structure.
|
||||
*
|
||||
* @return boolean If the statistics should be shown or not.
|
||||
*/
|
||||
private static function extractFillTransparent(array $data): bool
|
||||
{
|
||||
return static::parseBool(
|
||||
static::issetInArray($data, ['fillTransparent', 'show_statistics'])
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Extract a border width value.
|
||||
*
|
||||
|
@ -82,4 +181,196 @@ final class Box extends Item
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
* Generates inputs for form (specific).
|
||||
*
|
||||
* @param array $values Default values.
|
||||
*
|
||||
* @return array Of inputs.
|
||||
*
|
||||
* @throws Exception On error.
|
||||
*/
|
||||
public static function getFormInputs(array $values): array
|
||||
{
|
||||
// Default values.
|
||||
$values = static::getDefaultGeneralValues($values);
|
||||
|
||||
if ($values['tabSelected'] === 'general') {
|
||||
$inputs[] = [
|
||||
'arguments' => [
|
||||
'type' => 'hidden',
|
||||
'name' => 'tabGeneral',
|
||||
'value' => true,
|
||||
],
|
||||
];
|
||||
|
||||
// Size.
|
||||
$inputs[] = [
|
||||
'block_id' => 'size-item',
|
||||
'class' => 'flex-row flex-start w100p',
|
||||
'direct' => 1,
|
||||
'block_content' => [
|
||||
[
|
||||
'label' => __('Size'),
|
||||
],
|
||||
[
|
||||
'label' => __('width'),
|
||||
'arguments' => [
|
||||
'name' => 'width',
|
||||
'type' => 'number',
|
||||
'value' => $values['width'],
|
||||
'return' => true,
|
||||
'min' => 0,
|
||||
],
|
||||
],
|
||||
[
|
||||
'label' => __('height'),
|
||||
'arguments' => [
|
||||
'name' => 'height',
|
||||
'type' => 'number',
|
||||
'value' => $values['height'],
|
||||
'return' => true,
|
||||
'min' => 0,
|
||||
],
|
||||
],
|
||||
],
|
||||
];
|
||||
|
||||
// Position.
|
||||
$inputs[] = [
|
||||
'block_id' => 'position-item',
|
||||
'class' => 'flex-row flex-start w100p',
|
||||
'direct' => 1,
|
||||
'block_content' => [
|
||||
[
|
||||
'label' => __('Position'),
|
||||
],
|
||||
[
|
||||
'label' => __('X'),
|
||||
'arguments' => [
|
||||
'name' => 'x',
|
||||
'type' => 'number',
|
||||
'value' => $values['x'],
|
||||
'return' => true,
|
||||
'min' => 0,
|
||||
],
|
||||
],
|
||||
[
|
||||
'label' => __('Y'),
|
||||
'arguments' => [
|
||||
'name' => 'y',
|
||||
'type' => 'number',
|
||||
'value' => $values['y'],
|
||||
'return' => true,
|
||||
'min' => 0,
|
||||
],
|
||||
],
|
||||
],
|
||||
];
|
||||
|
||||
// Show on top.
|
||||
$inputs[] = [
|
||||
'label' => __('Show on top'),
|
||||
'arguments' => [
|
||||
'name' => 'isOnTop',
|
||||
'id' => 'isOnTop',
|
||||
'type' => 'switch',
|
||||
'value' => $values['isOnTop'],
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
// Default specific values.
|
||||
if (isset($values['borderColor']) === false) {
|
||||
$values['borderColor'] = '#000000';
|
||||
}
|
||||
|
||||
if (isset($values['borderWidth']) === false) {
|
||||
$values['borderWidth'] = 1;
|
||||
}
|
||||
|
||||
if (isset($values['fillColor']) === false) {
|
||||
$values['fillColor'] = '#ffffff';
|
||||
}
|
||||
|
||||
if ($values['tabSelected'] === 'specific') {
|
||||
// Border color.
|
||||
$inputs[] = [
|
||||
'label' => __('Border color'),
|
||||
'arguments' => [
|
||||
'wrapper' => 'div',
|
||||
'name' => 'borderColor',
|
||||
'type' => 'color',
|
||||
'value' => $values['borderColor'],
|
||||
'return' => true,
|
||||
],
|
||||
];
|
||||
|
||||
// Border Width.
|
||||
$inputs[] = [
|
||||
'label' => __('Border Width'),
|
||||
'arguments' => [
|
||||
'name' => 'borderWidth',
|
||||
'type' => 'number',
|
||||
'value' => $values['borderWidth'],
|
||||
'return' => true,
|
||||
'min' => 1,
|
||||
],
|
||||
];
|
||||
|
||||
// Fill color.
|
||||
$inputs[] = [
|
||||
'label' => __('Fill color'),
|
||||
'arguments' => [
|
||||
'wrapper' => 'div',
|
||||
'name' => 'fillColor',
|
||||
'type' => 'color',
|
||||
'value' => $values['fillColor'],
|
||||
'return' => true,
|
||||
],
|
||||
];
|
||||
|
||||
// Fill transparent.
|
||||
$inputs[] = [
|
||||
'label' => __('Fill transparent'),
|
||||
'arguments' => [
|
||||
'name' => 'fillTransparent',
|
||||
'id' => 'fillTransparent',
|
||||
'type' => 'switch',
|
||||
'value' => $values['fillTransparent'],
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
return $inputs;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Default values.
|
||||
*
|
||||
* @param array $values Array values.
|
||||
*
|
||||
* @return array Array with default values.
|
||||
*
|
||||
* @overrides Item->getDefaultGeneralValues.
|
||||
*/
|
||||
public function getDefaultGeneralValues(array $values): array
|
||||
{
|
||||
// Retrieve global - common inputs.
|
||||
$values = parent::getDefaultGeneralValues($values);
|
||||
|
||||
// Default values.
|
||||
if (isset($values['width']) === false) {
|
||||
$values['width'] = 100;
|
||||
}
|
||||
|
||||
if (isset($values['height']) === false) {
|
||||
$values['height'] = 100;
|
||||
}
|
||||
|
||||
return $values;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -20,6 +20,96 @@ final class Clock extends Item
|
|||
protected static $useLinkedVisualConsole = true;
|
||||
|
||||
|
||||
/**
|
||||
* Encode type item.
|
||||
*
|
||||
* @param array $data Data for encode.
|
||||
*
|
||||
* @return string Return color.
|
||||
*/
|
||||
protected function encodeColor(array $data): ?string
|
||||
{
|
||||
$color = null;
|
||||
if (isset($data['color']) === true) {
|
||||
if (empty($data['color']) === true) {
|
||||
$color = '#F0F0F0';
|
||||
} else {
|
||||
$color = $data['color'];
|
||||
}
|
||||
}
|
||||
|
||||
return $color;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return a valid representation of a record in database.
|
||||
*
|
||||
* @param array $data Input data.
|
||||
*
|
||||
* @return array Data structure representing a record in database.
|
||||
*
|
||||
* @overrides Item->encode.
|
||||
*/
|
||||
protected function encode(array $data): array
|
||||
{
|
||||
$return = parent::encode($data);
|
||||
|
||||
$color = static::encodeColor($data);
|
||||
if ($color !== null) {
|
||||
$return['fill_color'] = $color;
|
||||
}
|
||||
|
||||
$clock_animation = static::notEmptyStringOr(
|
||||
static::issetInArray(
|
||||
$data,
|
||||
[
|
||||
'clockType',
|
||||
'clock_animation',
|
||||
'clockAnimation',
|
||||
]
|
||||
),
|
||||
null
|
||||
);
|
||||
if ($clock_animation !== null) {
|
||||
$return['clock_animation'] = $clock_animation;
|
||||
}
|
||||
|
||||
$time_format = static::notEmptyStringOr(
|
||||
static::issetInArray(
|
||||
$data,
|
||||
[
|
||||
'clockFormat',
|
||||
'time_format',
|
||||
'timeFormat',
|
||||
]
|
||||
),
|
||||
null
|
||||
);
|
||||
if ($time_format !== null) {
|
||||
$return['time_format'] = $time_format;
|
||||
}
|
||||
|
||||
$timezone = static::notEmptyStringOr(
|
||||
static::issetInArray(
|
||||
$data,
|
||||
[
|
||||
'timezone',
|
||||
'timeZone',
|
||||
'time_zone',
|
||||
'clockTimezone',
|
||||
]
|
||||
),
|
||||
null
|
||||
);
|
||||
if ($timezone !== null) {
|
||||
$return['timezone'] = $timezone;
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns a valid representation of the model.
|
||||
*
|
||||
|
@ -151,4 +241,170 @@ final class Clock extends Item
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
* Generates inputs for form (specific).
|
||||
*
|
||||
* @param array $values Default values.
|
||||
*
|
||||
* @return array Of inputs.
|
||||
*
|
||||
* @throws Exception On error.
|
||||
*/
|
||||
public static function getFormInputs(array $values): array
|
||||
{
|
||||
// Default values.
|
||||
$values = static::getDefaultGeneralValues($values);
|
||||
|
||||
// Retrieve global - common inputs.
|
||||
$inputs = Item::getFormInputs($values);
|
||||
|
||||
if (is_array($inputs) !== true) {
|
||||
throw new Exception(
|
||||
'[Clock]::getFormInputs parent class return is not an array'
|
||||
);
|
||||
}
|
||||
|
||||
if ($values['tabSelected'] === 'specific') {
|
||||
// Time zone.
|
||||
$baseUrl = ui_get_full_url('/', false, false, false);
|
||||
$fields = [
|
||||
'Africa' => __('Africa'),
|
||||
'America' => __('America'),
|
||||
'Antarctica' => __('Antarctica'),
|
||||
'Arctic' => __('Arctic'),
|
||||
'Asia' => __('Asia'),
|
||||
'Atlantic' => __('Atlantic'),
|
||||
'Australia' => __('Australia'),
|
||||
'Europe' => __('Europe'),
|
||||
'Indian' => __('Indian'),
|
||||
'Pacific' => __('Pacific'),
|
||||
'UTC' => __('UTC'),
|
||||
];
|
||||
|
||||
if (isset($values['clockTimezone']) === false
|
||||
&& empty($values['clockTimezone']) === true
|
||||
) {
|
||||
$values['zone'] = 'Europe';
|
||||
$values['clockTimezone'] = 'Europe/Amsterdam';
|
||||
} else {
|
||||
$zone = explode('/', $values['clockTimezone']);
|
||||
$values['zone'] = $zone[0];
|
||||
}
|
||||
|
||||
$zones = self::zonesVC($values['zone']);
|
||||
|
||||
$inputs[] = [
|
||||
'block_id' => 'timeZone-item',
|
||||
'class' => 'flex-row flex-start w100p',
|
||||
'direct' => 1,
|
||||
'block_content' => [
|
||||
[
|
||||
'label' => __('Time zone'),
|
||||
],
|
||||
[
|
||||
'arguments' => [
|
||||
'type' => 'select',
|
||||
'fields' => $fields,
|
||||
'name' => 'zone',
|
||||
'selected' => $values['zone'],
|
||||
'script' => 'timeZoneVCChange(\''.$baseUrl.'\',\''.$values['vCId'].'\')',
|
||||
'return' => true,
|
||||
],
|
||||
],
|
||||
[
|
||||
'arguments' => [
|
||||
'type' => 'select',
|
||||
'fields' => $zones,
|
||||
'name' => 'clockTimezone',
|
||||
'selected' => $values['clockTimezone'],
|
||||
'return' => true,
|
||||
],
|
||||
],
|
||||
],
|
||||
];
|
||||
|
||||
// Clock animation.
|
||||
$fields = [
|
||||
'analogic' => __('Simple analogic'),
|
||||
'digital' => __('Simple digital'),
|
||||
];
|
||||
|
||||
$inputs[] = [
|
||||
'label' => __('Clock animation'),
|
||||
'arguments' => [
|
||||
'type' => 'select',
|
||||
'fields' => $fields,
|
||||
'name' => 'clockType',
|
||||
'selected' => $values['clockType'],
|
||||
'return' => true,
|
||||
'sort' => false,
|
||||
],
|
||||
];
|
||||
|
||||
// Time format.
|
||||
$fields = [
|
||||
'time' => __('Only time'),
|
||||
'datetime' => __('Time and date'),
|
||||
];
|
||||
|
||||
$inputs[] = [
|
||||
'label' => __('Time format'),
|
||||
'arguments' => [
|
||||
'type' => 'select',
|
||||
'fields' => $fields,
|
||||
'name' => 'clockFormat',
|
||||
'selected' => $values['clockFormat'],
|
||||
'return' => true,
|
||||
'sort' => false,
|
||||
],
|
||||
];
|
||||
|
||||
// Element color.
|
||||
$inputs[] = [
|
||||
'label' => __('Fill color'),
|
||||
'arguments' => [
|
||||
'wrapper' => 'div',
|
||||
'name' => 'color',
|
||||
'type' => 'color',
|
||||
'value' => $values['color'],
|
||||
'return' => true,
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
return $inputs;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Default values.
|
||||
*
|
||||
* @param array $values Array values.
|
||||
*
|
||||
* @return array Array with default values.
|
||||
*
|
||||
* @overrides Item->getDefaultGeneralValues.
|
||||
*/
|
||||
public function getDefaultGeneralValues(array $values): array
|
||||
{
|
||||
if (isset($values['isLinkEnabled']) === false) {
|
||||
$values['isLinkEnabled'] = false;
|
||||
}
|
||||
|
||||
// Retrieve global - common inputs.
|
||||
$values = parent::getDefaultGeneralValues($values);
|
||||
|
||||
// Default values.
|
||||
if (isset($values['width']) === false) {
|
||||
$values['width'] = 100;
|
||||
}
|
||||
|
||||
if (isset($values['height']) === false) {
|
||||
$values['height'] = 100;
|
||||
}
|
||||
|
||||
return $values;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -28,6 +28,98 @@ final class ColorCloud extends Item
|
|||
protected static $useLinkedModule = true;
|
||||
|
||||
|
||||
/**
|
||||
* Encode the ranges color value.
|
||||
*
|
||||
* @param array $data Unknown input data structure.
|
||||
*
|
||||
* @return array Ranges color.
|
||||
*/
|
||||
private static function encodeColorRanges(array $data): array
|
||||
{
|
||||
$colorRangeArray = [];
|
||||
|
||||
if (isset($data['colorRanges']) === true
|
||||
&& is_array($data['colorRanges']) === true
|
||||
) {
|
||||
if (empty($data['colorRanges']) === false) {
|
||||
foreach ($data['colorRanges'] as $colorRange) {
|
||||
if (\is_numeric($colorRange['fromValue']) === true
|
||||
&& \is_numeric($colorRange['toValue']) === true
|
||||
&& static::notEmptyStringOr(
|
||||
$colorRange['color'],
|
||||
null
|
||||
) !== null
|
||||
) {
|
||||
$colorRangeArray[] = [
|
||||
'color' => $colorRange['color'],
|
||||
'from_value' => (float) $colorRange['fromValue'],
|
||||
'to_value' => (float) $colorRange['toValue'],
|
||||
];
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$colorRangeArray = [];
|
||||
}
|
||||
}
|
||||
|
||||
return $colorRangeArray;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return a valid representation of a record in database.
|
||||
*
|
||||
* @param array $data Input data.
|
||||
*
|
||||
* @return array Data structure representing a record in database.
|
||||
*
|
||||
* @overrides Item->encode.
|
||||
*/
|
||||
protected function encode(array $data): array
|
||||
{
|
||||
$return = parent::encode($data);
|
||||
|
||||
$colorRanges = null;
|
||||
|
||||
$defaultColor = null;
|
||||
|
||||
if (isset($data['defaultColor']) === true) {
|
||||
$defaultColor = static::extractDefaultColor($data);
|
||||
}
|
||||
|
||||
if (isset($data['colorRanges']) === true) {
|
||||
$colorRanges = static::encodeColorRanges($data);
|
||||
}
|
||||
|
||||
if (empty($data['id']) === true) {
|
||||
$return['label'] = json_encode(
|
||||
[
|
||||
'default_color' => $defaultColor,
|
||||
'color_ranges' => $colorRanges,
|
||||
]
|
||||
);
|
||||
} else {
|
||||
$prevData = $this->toArray();
|
||||
$prevDataDefaultColor = static::extractDefaultColor(
|
||||
['defaultColor' => $prevData['defaultColor']]
|
||||
);
|
||||
$prevDataColorRanges = static::encodeColorRanges(
|
||||
['colorRanges' => $prevData['colorRanges']]
|
||||
);
|
||||
|
||||
$return['label'] = json_encode(
|
||||
[
|
||||
'default_color' => ($defaultColor !== null) ? $defaultColor : $prevDataDefaultColor,
|
||||
'color_ranges' => ($colorRanges !== null) ? $colorRanges : $prevDataColorRanges,
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns a valid representation of the model.
|
||||
*
|
||||
|
@ -143,10 +235,6 @@ final class ColorCloud extends Item
|
|||
{
|
||||
$dynamicDataEncoded = static::notEmptyStringOr($data['label'], null);
|
||||
|
||||
if ($dynamicDataEncoded === null) {
|
||||
throw new \InvalidArgumentException('dynamic data not found');
|
||||
}
|
||||
|
||||
$result = [];
|
||||
|
||||
try {
|
||||
|
@ -212,10 +300,6 @@ final class ColorCloud extends Item
|
|||
$moduleId = $linkedModule['moduleId'];
|
||||
$metaconsoleId = $linkedModule['metaconsoleId'];
|
||||
|
||||
if ($moduleId === null) {
|
||||
throw new \InvalidArgumentException('missing module Id');
|
||||
}
|
||||
|
||||
$dynamicData = static::extractDynamicData($data);
|
||||
// Set the initial color.
|
||||
$data['color'] = $dynamicData['defaultColor'];
|
||||
|
@ -278,4 +362,225 @@ final class ColorCloud extends Item
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
* Generates inputs for form (specific).
|
||||
*
|
||||
* @param array $values Default values.
|
||||
*
|
||||
* @return array Of inputs.
|
||||
*
|
||||
* @throws Exception On error.
|
||||
*/
|
||||
public static function getFormInputs(array $values): array
|
||||
{
|
||||
// Default values.
|
||||
$values = static::getDefaultGeneralValues($values);
|
||||
|
||||
// Retrieve global - common inputs.
|
||||
$inputs = Item::getFormInputs($values);
|
||||
|
||||
if (is_array($inputs) !== true) {
|
||||
throw new Exception(
|
||||
'[ColorCloud]::getFormInputs parent class return is not an array'
|
||||
);
|
||||
}
|
||||
|
||||
if ($values['tabSelected'] === 'specific') {
|
||||
// Autocomplete agents.
|
||||
$inputs[] = [
|
||||
'label' => __('Agent'),
|
||||
'arguments' => [
|
||||
'type' => 'autocomplete_agent',
|
||||
'name' => 'agentAlias',
|
||||
'id_agent_hidden' => $values['agentId'],
|
||||
'name_agent_hidden' => 'agentId',
|
||||
'server_id_hidden' => $values['metaconsoleId'],
|
||||
'name_server_hidden' => 'metaconsoleId',
|
||||
'return' => true,
|
||||
'module_input' => true,
|
||||
'module_name' => 'moduleId',
|
||||
'module_none' => false,
|
||||
],
|
||||
];
|
||||
|
||||
// Autocomplete module.
|
||||
$inputs[] = [
|
||||
'label' => __('Module'),
|
||||
'arguments' => [
|
||||
'type' => 'autocomplete_module',
|
||||
'fields' => $fields,
|
||||
'name' => 'moduleId',
|
||||
'selected' => $values['moduleId'],
|
||||
'return' => true,
|
||||
'sort' => false,
|
||||
'agent_id' => $values['agentId'],
|
||||
'metaconsole_id' => $values['metaconsoleId'],
|
||||
],
|
||||
];
|
||||
|
||||
// Default color.
|
||||
$inputs[] = [
|
||||
'label' => __('Default color'),
|
||||
'arguments' => [
|
||||
'wrapper' => 'div',
|
||||
'name' => 'defaultColor',
|
||||
'type' => 'color',
|
||||
'value' => $values['defaultColor'],
|
||||
'return' => true,
|
||||
],
|
||||
];
|
||||
|
||||
// Label.
|
||||
$inputs[] = [
|
||||
'label' => __('Add new range').':',
|
||||
];
|
||||
|
||||
$baseUrl = ui_get_full_url('/', false, false, false);
|
||||
// Default ranges.
|
||||
$inputs[] = [
|
||||
'block_id' => 'default-ranges',
|
||||
'class' => 'flex-row flex-start w100p',
|
||||
'direct' => 1,
|
||||
'block_content' => [
|
||||
[
|
||||
'label' => __('From'),
|
||||
'arguments' => [
|
||||
'id' => 'rangeDefaultFrom',
|
||||
'name' => 'rangeDefaultFrom',
|
||||
'type' => 'number',
|
||||
'value' => 0,
|
||||
'return' => true,
|
||||
'min' => 0,
|
||||
],
|
||||
],
|
||||
[
|
||||
'label' => __('To'),
|
||||
'arguments' => [
|
||||
'id' => 'rangeDefaultTo',
|
||||
'name' => 'rangeDefaultTo',
|
||||
'type' => 'number',
|
||||
'value' => 0,
|
||||
'return' => true,
|
||||
'min' => 0,
|
||||
],
|
||||
],
|
||||
[
|
||||
'label' => __('Color'),
|
||||
'arguments' => [
|
||||
'wrapper' => 'div',
|
||||
'name' => 'rangeDefaultColor',
|
||||
'type' => 'color',
|
||||
'value' => '#000000',
|
||||
'return' => true,
|
||||
],
|
||||
],
|
||||
[
|
||||
'arguments' => [
|
||||
'name' => 'add',
|
||||
'label' => '',
|
||||
'type' => 'button',
|
||||
'attributes' => 'class="add-item-img"',
|
||||
'return' => true,
|
||||
'script' => 'createColorRange(\''.$baseUrl.'\',\''.$values['vCId'].'\')',
|
||||
],
|
||||
],
|
||||
],
|
||||
];
|
||||
|
||||
// Label.
|
||||
$inputs[] = [
|
||||
'label' => __('Current ranges').':',
|
||||
];
|
||||
|
||||
if (isset($values['colorRanges']) === true
|
||||
&& is_array($values['colorRanges']) === true
|
||||
&& empty($values['colorRanges']) === false
|
||||
) {
|
||||
foreach ($values['colorRanges'] as $k => $v) {
|
||||
$uniqId = \uniqid();
|
||||
$inputs[] = [
|
||||
'block_id' => $uniqId,
|
||||
'class' => 'interval-color-ranges flex-row flex-start w100p',
|
||||
'direct' => 1,
|
||||
'block_content' => [
|
||||
[
|
||||
'label' => __('From'),
|
||||
'arguments' => [
|
||||
'name' => 'rangeFrom[]',
|
||||
'type' => 'number',
|
||||
'value' => $v['fromValue'],
|
||||
'return' => true,
|
||||
'min' => 0,
|
||||
],
|
||||
],
|
||||
[
|
||||
'label' => __('To'),
|
||||
'arguments' => [
|
||||
'name' => 'rangeTo[]',
|
||||
'type' => 'number',
|
||||
'value' => $v['toValue'],
|
||||
'return' => true,
|
||||
'min' => 0,
|
||||
],
|
||||
],
|
||||
[
|
||||
'label' => __('Color'),
|
||||
'arguments' => [
|
||||
'wrapper' => 'div',
|
||||
'id' => 'rangeColor'.$uniqId,
|
||||
'name' => 'rangeColor[]',
|
||||
'type' => 'color',
|
||||
'value' => $v['color'],
|
||||
'return' => true,
|
||||
],
|
||||
],
|
||||
[
|
||||
'arguments' => [
|
||||
'name' => 'remove-'.$uniqId,
|
||||
'label' => '',
|
||||
'type' => 'button',
|
||||
'attributes' => 'class="remove-item-img"',
|
||||
'return' => true,
|
||||
'script' => 'removeColorRange(
|
||||
\''.$uniqId.'\'
|
||||
)',
|
||||
],
|
||||
],
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $inputs;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Default values.
|
||||
*
|
||||
* @param array $values Array values.
|
||||
*
|
||||
* @return array Array with default values.
|
||||
*
|
||||
* @overrides Item->getDefaultGeneralValues.
|
||||
*/
|
||||
public function getDefaultGeneralValues(array $values): array
|
||||
{
|
||||
// Retrieve global - common inputs.
|
||||
$values = parent::getDefaultGeneralValues($values);
|
||||
|
||||
// Default values.
|
||||
if (isset($values['width']) === false) {
|
||||
$values['width'] = 300;
|
||||
}
|
||||
|
||||
if (isset($values['height']) === false) {
|
||||
$values['height'] = 180;
|
||||
}
|
||||
|
||||
return $values;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -124,9 +124,9 @@ final class DonutGraph extends Item
|
|||
// Maybe connect to node.
|
||||
$nodeConnected = false;
|
||||
if (\is_metaconsole() === true && $metaconsoleId !== null) {
|
||||
$server = \metaconsole_get_connection_by_id($metaconsoleId);
|
||||
$nodeConnected = \metaconsole_connect(
|
||||
null,
|
||||
$metaconsoleId
|
||||
$server
|
||||
) === NOERR;
|
||||
|
||||
if ($nodeConnected === false) {
|
||||
|
@ -147,29 +147,15 @@ final class DonutGraph extends Item
|
|||
$agentId,
|
||||
$moduleId
|
||||
);
|
||||
|
||||
$isString = (bool) \db_get_value_sql($sql);
|
||||
|
||||
// Restore connection.
|
||||
if ($nodeConnected === true) {
|
||||
\metaconsole_restore_db();
|
||||
}
|
||||
$width = (int) $data['width'];
|
||||
$height = (int) $data['height'];
|
||||
|
||||
if ($isString === true) {
|
||||
$graphData = \get_donut_module_data($moduleId);
|
||||
|
||||
$width = (int) $data['width'];
|
||||
$height = (int) $data['height'];
|
||||
|
||||
// Default width.
|
||||
if ($width <= 0) {
|
||||
$width = 300;
|
||||
}
|
||||
|
||||
// Default height.
|
||||
if ($height <= 0) {
|
||||
$height = 300;
|
||||
}
|
||||
|
||||
$data['html'] = \d3_donut_graph(
|
||||
(int) $data['id'],
|
||||
$width,
|
||||
|
@ -183,11 +169,125 @@ final class DonutGraph extends Item
|
|||
$src = '../../'.$src;
|
||||
}
|
||||
|
||||
$data['html'] = '<img src="'.$src.'">';
|
||||
$style = 'width:'.$width.'px; height:'.$height.'px;';
|
||||
$data['html'] = '<img src="'.$src.'" style="'.$style.'">';
|
||||
}
|
||||
|
||||
// Restore connection.
|
||||
if ($nodeConnected === true) {
|
||||
\metaconsole_restore_db();
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Generates inputs for form (specific).
|
||||
*
|
||||
* @param array $values Default values.
|
||||
*
|
||||
* @return array Of inputs.
|
||||
*
|
||||
* @throws Exception On error.
|
||||
*/
|
||||
public static function getFormInputs(array $values): array
|
||||
{
|
||||
// Default values.
|
||||
$values = static::getDefaultGeneralValues($values);
|
||||
|
||||
// Retrieve global - common inputs.
|
||||
$inputs = Item::getFormInputs($values);
|
||||
|
||||
if (is_array($inputs) !== true) {
|
||||
throw new Exception(
|
||||
'[DonutGraph]::getFormInputs parent class return is not an array'
|
||||
);
|
||||
}
|
||||
|
||||
if ($values['tabSelected'] === 'specific') {
|
||||
// Autocomplete agents.
|
||||
$inputs[] = [
|
||||
'label' => __('Agent'),
|
||||
'arguments' => [
|
||||
'type' => 'autocomplete_agent',
|
||||
'name' => 'agentAlias',
|
||||
'id_agent_hidden' => $values['agentId'],
|
||||
'name_agent_hidden' => 'agentId',
|
||||
'server_id_hidden' => $values['metaconsoleId'],
|
||||
'name_server_hidden' => 'metaconsoleId',
|
||||
'return' => true,
|
||||
'module_input' => true,
|
||||
'module_name' => 'moduleId',
|
||||
'module_none' => false,
|
||||
],
|
||||
];
|
||||
|
||||
// Autocomplete module.
|
||||
$inputs[] = [
|
||||
'label' => __('Module'),
|
||||
'arguments' => [
|
||||
'type' => 'autocomplete_module',
|
||||
'fields' => $fields,
|
||||
'name' => 'moduleId',
|
||||
'selected' => $values['moduleId'],
|
||||
'return' => true,
|
||||
'sort' => false,
|
||||
'agent_id' => $values['agentId'],
|
||||
'metaconsole_id' => $values['metaconsoleId'],
|
||||
],
|
||||
];
|
||||
|
||||
// Resume data color.
|
||||
$inputs[] = [
|
||||
'label' => __('Resume data color'),
|
||||
'arguments' => [
|
||||
'wrapper' => 'div',
|
||||
'name' => 'legendBackgroundColor',
|
||||
'type' => 'color',
|
||||
'value' => $values['legendBackgroundColor'],
|
||||
'return' => true,
|
||||
],
|
||||
];
|
||||
|
||||
// Inputs LinkedVisualConsole.
|
||||
$inputsLinkedVisualConsole = self::inputsLinkedVisualConsole(
|
||||
$values
|
||||
);
|
||||
foreach ($inputsLinkedVisualConsole as $key => $value) {
|
||||
$inputs[] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
return $inputs;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Default values.
|
||||
*
|
||||
* @param array $values Array values.
|
||||
*
|
||||
* @return array Array with default values.
|
||||
*
|
||||
* @overrides Item->getDefaultGeneralValues.
|
||||
*/
|
||||
public function getDefaultGeneralValues(array $values): array
|
||||
{
|
||||
// Retrieve global - common inputs.
|
||||
$values = parent::getDefaultGeneralValues($values);
|
||||
|
||||
// Default values.
|
||||
if (isset($values['width']) === false) {
|
||||
$values['width'] = 300;
|
||||
}
|
||||
|
||||
if (isset($values['height']) === false) {
|
||||
$values['height'] = 300;
|
||||
}
|
||||
|
||||
return $values;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -102,12 +102,6 @@ final class EventsHistory extends Item
|
|||
throw new \InvalidArgumentException('missing agent Id');
|
||||
}
|
||||
|
||||
// Default size.
|
||||
if ($data['width'] == 0 || $data['height'] == 0) {
|
||||
$data['width'] = 500;
|
||||
$data['height'] = 50;
|
||||
}
|
||||
|
||||
// Use the same HTML output as the old VC.
|
||||
$html = \graph_graphic_moduleevents(
|
||||
$agentId,
|
||||
|
@ -116,7 +110,8 @@ final class EventsHistory extends Item
|
|||
(int) $data['height'],
|
||||
static::extractMaxTime($data),
|
||||
'',
|
||||
true
|
||||
true,
|
||||
2
|
||||
);
|
||||
|
||||
$data['html'] = $html;
|
||||
|
@ -156,4 +151,121 @@ final class EventsHistory extends Item
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
* Generates inputs for form (specific).
|
||||
*
|
||||
* @param array $values Default values.
|
||||
*
|
||||
* @return array Of inputs.
|
||||
*
|
||||
* @throws Exception On error.
|
||||
*/
|
||||
public static function getFormInputs(array $values): array
|
||||
{
|
||||
// Default values.
|
||||
$values = static::getDefaultGeneralValues($values);
|
||||
|
||||
// Retrieve global - common inputs.
|
||||
$inputs = Item::getFormInputs($values);
|
||||
|
||||
if (is_array($inputs) !== true) {
|
||||
throw new Exception(
|
||||
'[EventHistory]::getFormInputs parent class return is not an array'
|
||||
);
|
||||
}
|
||||
|
||||
if ($values['tabSelected'] === 'specific') {
|
||||
// Autocomplete agents.
|
||||
$inputs[] = [
|
||||
'label' => __('Agent'),
|
||||
'arguments' => [
|
||||
'type' => 'autocomplete_agent',
|
||||
'name' => 'agentAlias',
|
||||
'id_agent_hidden' => $values['agentId'],
|
||||
'name_agent_hidden' => 'agentId',
|
||||
'server_id_hidden' => $values['metaconsoleId'],
|
||||
'name_server_hidden' => 'metaconsoleId',
|
||||
'return' => true,
|
||||
'module_input' => true,
|
||||
'module_name' => 'moduleId',
|
||||
'module_none' => false,
|
||||
],
|
||||
];
|
||||
|
||||
// Autocomplete module.
|
||||
$inputs[] = [
|
||||
'label' => __('Module'),
|
||||
'arguments' => [
|
||||
'type' => 'autocomplete_module',
|
||||
'fields' => $fields,
|
||||
'name' => 'moduleId',
|
||||
'selected' => $values['moduleId'],
|
||||
'return' => true,
|
||||
'sort' => false,
|
||||
'agent_id' => $values['agentId'],
|
||||
'metaconsole_id' => $values['metaconsoleId'],
|
||||
],
|
||||
];
|
||||
|
||||
// Type percentile.
|
||||
$fields = [
|
||||
'86400' => __('24h'),
|
||||
'43200' => __('12h'),
|
||||
'28800' => __('8h'),
|
||||
'7200' => __('2h'),
|
||||
'3600' => __('1h'),
|
||||
];
|
||||
|
||||
$inputs[] = [
|
||||
'label' => __('Max. Time'),
|
||||
'arguments' => [
|
||||
'type' => 'select',
|
||||
'fields' => $fields,
|
||||
'name' => 'maxTime',
|
||||
'selected' => $values['maxTime'],
|
||||
'return' => true,
|
||||
'sort' => false,
|
||||
],
|
||||
];
|
||||
|
||||
// Inputs LinkedVisualConsole.
|
||||
$inputsLinkedVisualConsole = self::inputsLinkedVisualConsole(
|
||||
$values
|
||||
);
|
||||
foreach ($inputsLinkedVisualConsole as $key => $value) {
|
||||
$inputs[] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
return $inputs;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Default values.
|
||||
*
|
||||
* @param array $values Array values.
|
||||
*
|
||||
* @return array Array with default values.
|
||||
*
|
||||
* @overrides Item->getDefaultGeneralValues.
|
||||
*/
|
||||
public function getDefaultGeneralValues(array $values): array
|
||||
{
|
||||
// Retrieve global - common inputs.
|
||||
$values = parent::getDefaultGeneralValues($values);
|
||||
|
||||
// Default values.
|
||||
if (isset($values['width']) === false) {
|
||||
$values['width'] = 500;
|
||||
}
|
||||
|
||||
if (isset($values['height']) === false) {
|
||||
$values['height'] = 70;
|
||||
}
|
||||
|
||||
return $values;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -34,6 +34,68 @@ final class Group extends Item
|
|||
protected static $indexCacheByUser = true;
|
||||
|
||||
|
||||
/**
|
||||
* Get the "show statistics" switch value.
|
||||
*
|
||||
* @param array $data Unknown input data structure.
|
||||
*
|
||||
* @return mixed If the statistics should be shown or not.
|
||||
*/
|
||||
private static function getShowStatistics(array $data)
|
||||
{
|
||||
return static::issetInArray(
|
||||
$data,
|
||||
[
|
||||
'showStatistics',
|
||||
'show_statistics',
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Extract a group Id (for ACL) value.
|
||||
*
|
||||
* @param array $data Unknown input data structure.
|
||||
*
|
||||
* @return integer Valid identifier of a group.
|
||||
*/
|
||||
private static function getGroupId(array $data)
|
||||
{
|
||||
return static::parseIntOr(
|
||||
static::issetInArray($data, ['id_group', 'groupId']),
|
||||
null
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return a valid representation of a record in database.
|
||||
*
|
||||
* @param array $data Input data.
|
||||
*
|
||||
* @return array Data structure representing a record in database.
|
||||
*
|
||||
* @overrides Item->encode.
|
||||
*/
|
||||
protected function encode(array $data): array
|
||||
{
|
||||
$return = parent::encode($data);
|
||||
|
||||
$id_group = static::getGroupId($data);
|
||||
if ($id_group !== null) {
|
||||
$return['id_group'] = $id_group;
|
||||
}
|
||||
|
||||
$show_statistics = static::getShowStatistics($data);
|
||||
if ($show_statistics !== null) {
|
||||
$return['show_statistics'] = static::parseBool($show_statistics);
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns a valid representation of the model.
|
||||
*
|
||||
|
@ -209,7 +271,7 @@ final class Group extends Item
|
|||
$agentsOk = \agents_get_agents(
|
||||
[
|
||||
'id_grupo' => $groupId,
|
||||
'status' => AGENT_STATUS_OK,
|
||||
'status' => AGENT_STATUS_NORMAL,
|
||||
],
|
||||
['COUNT(*) AS total'],
|
||||
'AR',
|
||||
|
@ -221,20 +283,39 @@ final class Group extends Item
|
|||
$numNormal = $agentsOk[0]['total'];
|
||||
|
||||
$numTotal = ($numCritical + $numWarning + $numUnknown + $numNormal);
|
||||
|
||||
$agentStats = [
|
||||
'critical' => ($numCritical / $numTotal * 100),
|
||||
'warning' => ($numWarning / $numTotal * 100),
|
||||
'normal' => ($numNormal / $numTotal * 100),
|
||||
'unknown' => ($numUnknown / $numTotal * 100),
|
||||
'critical' => 0,
|
||||
'warning' => 0,
|
||||
'normal' => 0,
|
||||
'unknown' => 0,
|
||||
];
|
||||
if ($numTotal !== 0) {
|
||||
$agentStats = [
|
||||
'critical' => ($numCritical / $numTotal * 100),
|
||||
'warning' => ($numWarning / $numTotal * 100),
|
||||
'normal' => ($numNormal / $numTotal * 100),
|
||||
'unknown' => ($numUnknown / $numTotal * 100),
|
||||
];
|
||||
}
|
||||
|
||||
$groupName = \groups_get_name($groupId, true);
|
||||
$data['html'] = static::printStatsTable(
|
||||
$groupName,
|
||||
$agentStats,
|
||||
(int) $data['width'],
|
||||
(int) $data['height']
|
||||
$agentStats
|
||||
);
|
||||
|
||||
if (isset($data['width']) === false
|
||||
|| (int) $data['width'] === 0
|
||||
) {
|
||||
$data['width'] = 500;
|
||||
}
|
||||
|
||||
if (isset($data['height']) === false
|
||||
|| (int) $data['height'] === 0
|
||||
) {
|
||||
$data['height'] = 70;
|
||||
}
|
||||
} else {
|
||||
if (\is_metaconsole()) {
|
||||
$groupFilter = $groupId;
|
||||
|
@ -306,100 +387,56 @@ final class Group extends Item
|
|||
/**
|
||||
* HTML representation for the agent stats of a group.
|
||||
*
|
||||
* @param string $groupName Group name.
|
||||
* @param array $agentStats Data structure with the agent statistics.
|
||||
* @param integer $width Width.
|
||||
* @param integer $height Height.
|
||||
* @param string $groupName Group name.
|
||||
* @param array $agentStats Data structure with the agent statistics.
|
||||
*
|
||||
* @return string HTML representation.
|
||||
*/
|
||||
private static function printStatsTable(
|
||||
string $groupName,
|
||||
array $agentStats,
|
||||
int $width=520,
|
||||
int $height=80
|
||||
array $agentStats
|
||||
): string {
|
||||
$width = ($width > 0) ? $width : 520;
|
||||
$height = ($height > 0) ? $height : 80;
|
||||
|
||||
$tableStyle = \join(
|
||||
[
|
||||
'width:'.$width.'px;',
|
||||
'height:'.$height.'px;',
|
||||
'text-align:center;',
|
||||
]
|
||||
);
|
||||
$headStyle = \join(
|
||||
[
|
||||
'text-align:center;',
|
||||
'background-color:#9d9ea0;',
|
||||
'color:black;',
|
||||
'font-weight:bold;',
|
||||
]
|
||||
);
|
||||
$valueStyle = \join(
|
||||
[
|
||||
'margin-left: 2%;',
|
||||
'color: #FFF;',
|
||||
'font-size: 12px;',
|
||||
'display: inline;',
|
||||
'background-color: #e63c52;',
|
||||
'position: relative;',
|
||||
'height: 80%;',
|
||||
'width: 9.4%;',
|
||||
'height: 80%;',
|
||||
'border-radius: 2px;',
|
||||
'text-align: center;',
|
||||
'padding: 5px;',
|
||||
]
|
||||
);
|
||||
$nameStyle = \join(
|
||||
[
|
||||
'background-color: white;',
|
||||
'color: black;',
|
||||
'font-size: 12px;',
|
||||
'display: inline;',
|
||||
'display: inline;',
|
||||
'position:relative;',
|
||||
'width: 9.4%;',
|
||||
'height: 80%;',
|
||||
'border-radius: 2px;',
|
||||
'text-align: center;',
|
||||
'padding: 5px;',
|
||||
]
|
||||
);
|
||||
|
||||
$html = '<table class="databox" style="'.$tableStyle.'">';
|
||||
$html .= '<tr style="height:10%;">';
|
||||
$html .= '<th style="'.$headStyle.'">'.$groupName.'</th>';
|
||||
$html .= '</tr>';
|
||||
$html .= '<tr style="background-color:whitesmoke;height:90%;">';
|
||||
$html .= '<td>';
|
||||
$critical = \number_format($agentStats['critical'], 2).'%';
|
||||
$warning = \number_format($agentStats['warning'], 2).'%';
|
||||
$normal = \number_format($agentStats['normal'], 2).'%';
|
||||
$unknown = \number_format($agentStats['unknown'], 2).'%';
|
||||
|
||||
$html = '<div class="group-container">';
|
||||
$html .= '<div class="group-item-title">';
|
||||
$html .= $groupName;
|
||||
$html .= '</div>';
|
||||
$html .= '<div class="group-item-info">';
|
||||
// Critical.
|
||||
$html .= '<div style="'.$valueStyle.'background-color: #e63c52;">';
|
||||
$html .= \number_format($agentStats['critical'], 2).'%';
|
||||
$html .= '<div class="group-item-info-container">';
|
||||
$html .= '<div class="value-style" style="background-color: #e63c52;">';
|
||||
$html .= $critical;
|
||||
$html .= '</div>';
|
||||
$html .= '<div class="name-style">'.__('Critical').'</div>';
|
||||
$html .= '</div>';
|
||||
$html .= '<div style="'.$nameStyle.'">'.__('Critical').'</div>';
|
||||
// Warning.
|
||||
$html .= '<div style="'.$valueStyle.'background-color: #f8db3f;">';
|
||||
$html .= \number_format($agentStats['warning'], 2).'%';
|
||||
$html .= '<div class="group-item-info-container">';
|
||||
$html .= '<div class="value-style" style="background-color: #f8db3f;">';
|
||||
$html .= $warning;
|
||||
$html .= '</div>';
|
||||
$html .= '<div class="name-style">'.__('Warning').'</div>';
|
||||
$html .= '</div>';
|
||||
$html .= '<div style="'.$nameStyle.'">'.__('Warning').'</div>';
|
||||
// Normal.
|
||||
$html .= '<div style="'.$valueStyle.'background-color: #84b83c;">';
|
||||
$html .= \number_format($agentStats['normal'], 2).'%';
|
||||
$html .= '<div class="group-item-info-container">';
|
||||
$html .= '<div class="value-style" style="background-color: #84b83c;">';
|
||||
$html .= $normal;
|
||||
$html .= '</div>';
|
||||
$html .= '<div class="name-style">'.__('Normal').'</div>';
|
||||
$html .= '</div>';
|
||||
$html .= '<div style="'.$nameStyle.'">'.__('Normal').'</div>';
|
||||
// Unknown.
|
||||
$html .= '<div style="'.$valueStyle.'background-color: #9d9ea0;">';
|
||||
$html .= \number_format($agentStats['unknown'], 2).'%';
|
||||
$html .= '<div class="group-item-info-container">';
|
||||
$html .= '<div class="value-style" style="background-color: #9d9ea0;">';
|
||||
$html .= $unknown;
|
||||
$html .= '</div>';
|
||||
$html .= '<div class="name-style">'.__('Unknown').'</div>';
|
||||
$html .= '</div>';
|
||||
$html .= '<div style="'.$nameStyle.'">'.__('Unknown').'</div>';
|
||||
|
||||
$html .= '</td>';
|
||||
$html .= '</tr>';
|
||||
$html .= '</table>';
|
||||
$html .= '</div>';
|
||||
$html .= '</div>';
|
||||
|
||||
return $html;
|
||||
}
|
||||
|
@ -447,4 +484,95 @@ final class Group extends Item
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
* Generates inputs for form (specific).
|
||||
*
|
||||
* @param array $values Default values.
|
||||
*
|
||||
* @return array Of inputs.
|
||||
*
|
||||
* @throws Exception On error.
|
||||
*/
|
||||
public static function getFormInputs(array $values): array
|
||||
{
|
||||
// Default values.
|
||||
$values = static::getDefaultGeneralValues($values);
|
||||
|
||||
// Retrieve global - common inputs.
|
||||
$inputs = Item::getFormInputs($values);
|
||||
|
||||
if (is_array($inputs) !== true) {
|
||||
throw new Exception(
|
||||
'[Group]::getFormInputs parent class return is not an array'
|
||||
);
|
||||
}
|
||||
|
||||
if ($values['tabSelected'] === 'specific') {
|
||||
// List images VC.
|
||||
if (isset($values['imageSrc']) === false) {
|
||||
$values['imageSrc'] = 'appliance';
|
||||
}
|
||||
|
||||
$baseUrl = ui_get_full_url('/', false, false, false);
|
||||
|
||||
$inputs[] = [
|
||||
'label' => __('Image'),
|
||||
'arguments' => [
|
||||
'type' => 'select',
|
||||
'fields' => self::getListImagesVC(),
|
||||
'name' => 'imageSrc',
|
||||
'selected' => $values['imageSrc'],
|
||||
'script' => 'imageVCChange(\''.$baseUrl.'\',\''.$values['vCId'].'\')',
|
||||
'return' => true,
|
||||
],
|
||||
];
|
||||
|
||||
$images = self::imagesElementsVC($values['imageSrc']);
|
||||
|
||||
$inputs[] = [
|
||||
'block_id' => 'image-item',
|
||||
'class' => 'flex-row flex-end w100p',
|
||||
'direct' => 1,
|
||||
'block_content' => [
|
||||
['label' => $images],
|
||||
],
|
||||
];
|
||||
|
||||
// Group.
|
||||
$inputs[] = [
|
||||
'label' => __('Group'),
|
||||
'arguments' => [
|
||||
'type' => 'select_groups',
|
||||
'name' => 'groupId',
|
||||
'returnAllGroup' => true,
|
||||
'privilege' => $values['access'],
|
||||
'selected' => $values['groupId'],
|
||||
'return' => true,
|
||||
],
|
||||
];
|
||||
|
||||
// Show statistics.
|
||||
$inputs[] = [
|
||||
'label' => __('Show statistics'),
|
||||
'arguments' => [
|
||||
'name' => 'showStatistics',
|
||||
'id' => 'showStatistics',
|
||||
'type' => 'switch',
|
||||
'value' => $values['showStatistics'],
|
||||
],
|
||||
];
|
||||
|
||||
// Inputs LinkedVisualConsole.
|
||||
$inputsLinkedVisualConsole = self::inputsLinkedVisualConsole(
|
||||
$values
|
||||
);
|
||||
foreach ($inputsLinkedVisualConsole as $key => $value) {
|
||||
$inputs[] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
return $inputs;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -129,4 +129,101 @@ final class Icon extends Item
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
* Generates inputs for form (specific).
|
||||
*
|
||||
* @param array $values Default values.
|
||||
*
|
||||
* @return array Of inputs.
|
||||
*
|
||||
* @throws Exception On error.
|
||||
*/
|
||||
public static function getFormInputs(array $values): array
|
||||
{
|
||||
// Default values.
|
||||
$values = static::getDefaultGeneralValues($values);
|
||||
|
||||
// Retrieve global - common inputs.
|
||||
$inputs = Item::getFormInputs($values);
|
||||
|
||||
if (is_array($inputs) !== true) {
|
||||
throw new Exception(
|
||||
'[Icon]::getFormInputs parent class return is not an array'
|
||||
);
|
||||
}
|
||||
|
||||
if ($values['tabSelected'] === 'specific') {
|
||||
// List images VC.
|
||||
if (isset($values['imageSrc']) === false) {
|
||||
$values['imageSrc'] = 'appliance';
|
||||
} else {
|
||||
$explode_url = explode('/', $values['imageSrc']);
|
||||
$total = count($explode_url);
|
||||
$values['imageSrc'] = substr(
|
||||
$explode_url[($total - 1)],
|
||||
0,
|
||||
-4
|
||||
);
|
||||
}
|
||||
|
||||
$baseUrl = ui_get_full_url('/', false, false, false);
|
||||
|
||||
$inputs[] = [
|
||||
'label' => __('Image'),
|
||||
'arguments' => [
|
||||
'type' => 'select',
|
||||
'fields' => self::getListImagesVC(),
|
||||
'name' => 'imageSrc',
|
||||
'selected' => $values['imageSrc'],
|
||||
'script' => 'imageVCChange(\''.$baseUrl.'\',\''.$values['vCId'].'\',1)',
|
||||
'return' => true,
|
||||
],
|
||||
];
|
||||
|
||||
$images = self::imagesElementsVC($values['imageSrc'], true);
|
||||
|
||||
$inputs[] = [
|
||||
'block_id' => 'image-item',
|
||||
'class' => 'flex-row flex-end w100p',
|
||||
'direct' => 1,
|
||||
'block_content' => [
|
||||
['label' => $images],
|
||||
],
|
||||
];
|
||||
|
||||
// Inputs LinkedVisualConsole.
|
||||
$inputsLinkedVisualConsole = self::inputsLinkedVisualConsole(
|
||||
$values
|
||||
);
|
||||
foreach ($inputsLinkedVisualConsole as $key => $value) {
|
||||
$inputs[] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
return $inputs;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Default values.
|
||||
*
|
||||
* @param array $values Array values.
|
||||
*
|
||||
* @return array Array with default values.
|
||||
*
|
||||
* @overrides Item->getDefaultGeneralValues.
|
||||
*/
|
||||
public function getDefaultGeneralValues(array $values): array
|
||||
{
|
||||
if (isset($values['isLinkEnabled']) === false) {
|
||||
$values['isLinkEnabled'] = false;
|
||||
}
|
||||
|
||||
// Retrieve global - common inputs.
|
||||
$values = parent::getDefaultGeneralValues($values);
|
||||
|
||||
return $values;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -20,30 +20,6 @@ final class Label extends Item
|
|||
protected static $useLinkedVisualConsole = true;
|
||||
|
||||
|
||||
/**
|
||||
* Validate the received data structure to ensure if we can extract the
|
||||
* values required to build the model.
|
||||
*
|
||||
* @param array $data Input data.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @throws \InvalidArgumentException If any input value is considered
|
||||
* invalid.
|
||||
*
|
||||
* @overrides Item->validateData.
|
||||
*/
|
||||
protected function validateData(array $data): void
|
||||
{
|
||||
parent::validateData($data);
|
||||
if (static::notEmptyStringOr(static::issetInArray($data, ['label']), null) === null) {
|
||||
throw new \InvalidArgumentException(
|
||||
'the label property is required and should be a not empty string'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns a valid representation of the model.
|
||||
*
|
||||
|
@ -61,4 +37,62 @@ final class Label extends Item
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
* Generates inputs for form (specific).
|
||||
*
|
||||
* @param array $values Default values.
|
||||
*
|
||||
* @return array Of inputs.
|
||||
*
|
||||
* @throws Exception On error.
|
||||
*/
|
||||
public static function getFormInputs(array $values): array
|
||||
{
|
||||
// Default values.
|
||||
$values = static::getDefaultGeneralValues($values);
|
||||
|
||||
// Retrieve global - common inputs.
|
||||
$inputs = Item::getFormInputs($values);
|
||||
|
||||
if (is_array($inputs) !== true) {
|
||||
throw new Exception(
|
||||
'[Label]::getFormInputs parent class return is not an array'
|
||||
);
|
||||
}
|
||||
|
||||
return $inputs;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Default values.
|
||||
*
|
||||
* @param array $values Array values.
|
||||
*
|
||||
* @return array Array with default values.
|
||||
*
|
||||
* @overrides Item->getDefaultGeneralValues.
|
||||
*/
|
||||
public function getDefaultGeneralValues(array $values): array
|
||||
{
|
||||
if (isset($values['isLinkEnabled']) === false) {
|
||||
$values['isLinkEnabled'] = false;
|
||||
}
|
||||
|
||||
// Retrieve global - common inputs.
|
||||
$values = parent::getDefaultGeneralValues($values);
|
||||
|
||||
// Default values.
|
||||
if (isset($values['width']) === false) {
|
||||
$values['width'] = 10;
|
||||
}
|
||||
|
||||
if (isset($values['height']) === false) {
|
||||
$values['height'] = 10;
|
||||
}
|
||||
|
||||
return $values;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -218,64 +218,74 @@ final class Line extends Model
|
|||
protected function encode(array $data): array
|
||||
{
|
||||
$result = [];
|
||||
$result['type'] = LINE_ITEM;
|
||||
|
||||
$id = static::getId($data);
|
||||
if ($id) {
|
||||
$result['id'] = $id;
|
||||
}
|
||||
|
||||
$id_layout = static::getIdLayout($data);
|
||||
if ($id_layout) {
|
||||
$result['id_layout'] = $id_layout;
|
||||
$layoutId = static::getIdLayout($data);
|
||||
if ($layoutId > 0) {
|
||||
$result['id_layout'] = $layoutId;
|
||||
}
|
||||
|
||||
$pos_x = static::parseIntOr(
|
||||
static::issetInArray($data, ['x', 'pos_x', 'posX']),
|
||||
$startX = static::parseIntOr(
|
||||
static::issetInArray($data, ['pos_x', 'startX']),
|
||||
null
|
||||
);
|
||||
if ($pos_x !== null) {
|
||||
$result['pos_x'] = $pos_x;
|
||||
if ($startX !== null) {
|
||||
$result['pos_x'] = $startX;
|
||||
}
|
||||
|
||||
$pos_y = static::parseIntOr(
|
||||
static::issetInArray($data, ['y', 'pos_y', 'posY']),
|
||||
$startY = static::parseIntOr(
|
||||
static::issetInArray($data, ['pos_y', 'startY']),
|
||||
null
|
||||
);
|
||||
if ($pos_y !== null) {
|
||||
$result['pos_y'] = $pos_y;
|
||||
if ($startY !== null) {
|
||||
$result['pos_y'] = $startY;
|
||||
}
|
||||
|
||||
$height = static::getHeight($data);
|
||||
if ($height !== null) {
|
||||
$result['height'] = $height;
|
||||
}
|
||||
|
||||
$width = static::getWidth($data);
|
||||
if ($width !== null) {
|
||||
$result['width'] = $width;
|
||||
}
|
||||
|
||||
$type = static::parseIntOr(
|
||||
static::issetInArray($data, ['type']),
|
||||
$endX = static::parseIntOr(
|
||||
static::issetInArray($data, ['width', 'endX']),
|
||||
null
|
||||
);
|
||||
if ($type !== null) {
|
||||
$result['type'] = $type;
|
||||
if ($endX !== null) {
|
||||
$result['width'] = $endX;
|
||||
}
|
||||
|
||||
$border_width = static::getBorderWidth($data);
|
||||
if ($border_width !== null) {
|
||||
$result['border_width'] = $border_width;
|
||||
$endY = static::parseIntOr(
|
||||
static::issetInArray($data, ['height', 'endY']),
|
||||
null
|
||||
);
|
||||
if ($endY !== null) {
|
||||
$result['height'] = $endY;
|
||||
}
|
||||
|
||||
$border_color = static::extractBorderColor($data);
|
||||
if ($border_color !== null) {
|
||||
$result['border_color'] = $border_color;
|
||||
$borderWidth = static::getBorderWidth($data);
|
||||
if ($borderWidth !== null) {
|
||||
if ($borderWidth < 1) {
|
||||
$borderWidth = 1;
|
||||
}
|
||||
|
||||
$result['border_width'] = $borderWidth;
|
||||
}
|
||||
|
||||
$show_on_top = static::issetInArray($data, ['isOnTop', 'show_on_top', 'showOnTop']);
|
||||
if ($show_on_top !== null) {
|
||||
$result['show_on_top'] = static::parseBool($show_on_top);
|
||||
$borderColor = static::extractBorderColor($data);
|
||||
if ($borderColor !== null) {
|
||||
$result['border_color'] = $borderColor;
|
||||
}
|
||||
|
||||
$showOnTop = static::issetInArray(
|
||||
$data,
|
||||
[
|
||||
'isOnTop',
|
||||
'show_on_top',
|
||||
'showOnTop',
|
||||
]
|
||||
);
|
||||
if ($showOnTop !== null) {
|
||||
$result['show_on_top'] = static::parseBool($showOnTop);
|
||||
}
|
||||
|
||||
return $result;
|
||||
|
@ -367,42 +377,122 @@ final class Line extends Model
|
|||
*
|
||||
* @param array $data Unknown input data structure.
|
||||
*
|
||||
* @return boolean The modeled element data structure stored into the DB.
|
||||
* @return integer The modeled element data structure stored into the DB.
|
||||
*
|
||||
* @overrides Model::save.
|
||||
*/
|
||||
public function save(array $data=[]): bool
|
||||
public function save(array $data=[]): int
|
||||
{
|
||||
$data_model = $this->encode($this->toArray());
|
||||
$newData = $this->encode($data);
|
||||
|
||||
$save = \array_merge($data_model, $newData);
|
||||
|
||||
if (!empty($save)) {
|
||||
if (empty($save['id'])) {
|
||||
if (empty($data) === false) {
|
||||
if (empty($data['id']) === true) {
|
||||
// Insert.
|
||||
$save = static::encode($data);
|
||||
$result = \db_process_sql_insert('tlayout_data', $save);
|
||||
if ($result !== false) {
|
||||
$item = static::fromDB(['id' => $result]);
|
||||
$item->setData($item->toArray());
|
||||
}
|
||||
} else {
|
||||
// Update.
|
||||
$result = \db_process_sql_update('tlayout_data', $save, ['id' => $save['id']]);
|
||||
$dataModelEncode = $this->encode($this->toArray());
|
||||
$dataEncode = $this->encode($data);
|
||||
|
||||
$save = array_merge($dataModelEncode, $dataEncode);
|
||||
|
||||
$result = \db_process_sql_update(
|
||||
'tlayout_data',
|
||||
$save,
|
||||
['id' => $save['id']]
|
||||
);
|
||||
// Invalidate the item's cache.
|
||||
if ($result !== false && $result > 0) {
|
||||
$item = static::fromDB(['id' => $save['id']]);
|
||||
// Update the model.
|
||||
if (empty($item) === false) {
|
||||
$this->setData($item->toArray());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Update the model.
|
||||
if ($result) {
|
||||
if (empty($save['id'])) {
|
||||
$item = static::fromDB(['id' => $result]);
|
||||
} else {
|
||||
$item = static::fromDB(['id' => $save['id']]);
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
if (!empty($item)) {
|
||||
$this->setData($item->toArray());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a line in the database
|
||||
*
|
||||
* @param integer $itemId Identifier of the Item.
|
||||
*
|
||||
* @return boolean The modeled element data structure stored into the DB.
|
||||
*
|
||||
* @overrides Model::delete.
|
||||
*/
|
||||
public function delete(int $itemId): bool
|
||||
{
|
||||
$result = db_process_sql_delete(
|
||||
'tlayout_data',
|
||||
['id' => $itemId]
|
||||
);
|
||||
|
||||
return (bool) $result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Generates inputs for form (global, common).
|
||||
*
|
||||
* @param array $values Default values.
|
||||
*
|
||||
* @return array Of inputs.
|
||||
*/
|
||||
public static function getFormInputs(array $values): array
|
||||
{
|
||||
$inputs = [];
|
||||
|
||||
if ($values['tabSelected'] === 'specific') {
|
||||
// Width.
|
||||
if ($values['borderWidth'] < 1) {
|
||||
$values['borderWidth'] = 1;
|
||||
}
|
||||
|
||||
$inputs[] = [
|
||||
'label' => __('Width'),
|
||||
'arguments' => [
|
||||
'name' => 'borderWidth',
|
||||
'type' => 'number',
|
||||
'value' => $values['borderWidth'],
|
||||
'return' => true,
|
||||
'min' => 1,
|
||||
],
|
||||
];
|
||||
|
||||
// Color.
|
||||
$inputs[] = [
|
||||
'label' => __('Color'),
|
||||
'arguments' => [
|
||||
'wrapper' => 'div',
|
||||
'name' => 'borderColor',
|
||||
'type' => 'color',
|
||||
'value' => $values['borderColor'],
|
||||
'return' => true,
|
||||
],
|
||||
];
|
||||
|
||||
// Show on top.
|
||||
$inputs[] = [
|
||||
'label' => __('Show on top'),
|
||||
'arguments' => [
|
||||
'name' => 'isOnTop',
|
||||
'id' => 'isOnTop',
|
||||
'type' => 'switch',
|
||||
'value' => $values['isOnTop'],
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
return $inputs;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -35,6 +35,97 @@ final class ModuleGraph extends Item
|
|||
protected static $useHtmlOutput = true;
|
||||
|
||||
|
||||
/**
|
||||
* Extract the "show Legend" switch value.
|
||||
*
|
||||
* @param array $data Unknown input data structure.
|
||||
*
|
||||
* @return mixed If the statistics should be shown or not.
|
||||
*/
|
||||
private static function getShowLegend(array $data)
|
||||
{
|
||||
return static::issetInArray($data, ['showLegend', 'show_statistics']);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return a valid representation of a record in database.
|
||||
*
|
||||
* @param array $data Input data.
|
||||
*
|
||||
* @return array Data structure representing a record in database.
|
||||
*
|
||||
* @overrides Item->encode.
|
||||
*/
|
||||
protected function encode(array $data): array
|
||||
{
|
||||
$return = parent::encode($data);
|
||||
|
||||
$id_custom_graph = static::extractIdCustomGraph($data);
|
||||
if ($id_custom_graph !== null) {
|
||||
$return['id_custom_graph'] = $id_custom_graph;
|
||||
}
|
||||
|
||||
$type_graph = static::getTypeGraph($data);
|
||||
if ($type_graph !== null) {
|
||||
$return['type_graph'] = $type_graph;
|
||||
}
|
||||
|
||||
$show_legend = static::getShowLegend($data);
|
||||
if ($show_legend !== null) {
|
||||
$return['show_statistics'] = static::parseBool($show_legend);
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Extract a custom id graph value.
|
||||
*
|
||||
* @param array $data Unknown input data structure.
|
||||
*
|
||||
* @return integer Valid identifier of an agent.
|
||||
*/
|
||||
private static function extractIdCustomGraph(array $data)
|
||||
{
|
||||
return static::parseIntOr(
|
||||
static::issetInArray(
|
||||
$data,
|
||||
[
|
||||
'id_custom_graph',
|
||||
'idCustomGraph',
|
||||
'customGraphId',
|
||||
]
|
||||
),
|
||||
null
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Extract a type graph value.
|
||||
*
|
||||
* @param array $data Unknown input data structure.
|
||||
*
|
||||
* @return string One of 'vertical' or 'horizontal'. 'vertical' by default.
|
||||
*/
|
||||
private static function getTypeGraph(array $data)
|
||||
{
|
||||
return static::notEmptyStringOr(
|
||||
static::issetInArray(
|
||||
$data,
|
||||
[
|
||||
'typeGraph',
|
||||
'type_graph',
|
||||
'graphType',
|
||||
]
|
||||
),
|
||||
null
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns a valid representation of the model.
|
||||
*
|
||||
|
@ -50,6 +141,7 @@ final class ModuleGraph extends Item
|
|||
$return['type'] = MODULE_GRAPH;
|
||||
$return['backgroundType'] = static::extractBackgroundType($data);
|
||||
$return['period'] = static::extractPeriod($data);
|
||||
$return['showLegend'] = static::extractShowLegend($data);
|
||||
|
||||
$customGraphId = static::extractCustomGraphId($data);
|
||||
|
||||
|
@ -68,7 +160,8 @@ final class ModuleGraph extends Item
|
|||
*
|
||||
* @param array $data Unknown input data structure.
|
||||
*
|
||||
* @return string 'transparent', 'white' or 'black'. 'transparent' by default.
|
||||
* @return string 'transparent', 'white' or 'black'.
|
||||
* 'transparent' by default.
|
||||
*/
|
||||
private static function extractBackgroundType(array $data): string
|
||||
{
|
||||
|
@ -102,6 +195,21 @@ final class ModuleGraph extends Item
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
* Extract the "show Legend" switch value.
|
||||
*
|
||||
* @param array $data Unknown input data structure.
|
||||
*
|
||||
* @return boolean If the statistics should be shown or not.
|
||||
*/
|
||||
private static function extractShowLegend(array $data): bool
|
||||
{
|
||||
return static::parseBool(
|
||||
static::issetInArray($data, ['showLegend', 'show_statistics'])
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Extract a custom graph Id value.
|
||||
*
|
||||
|
@ -168,10 +276,11 @@ final class ModuleGraph extends Item
|
|||
\enterprise_include_once('include/functions_metaconsole.php');
|
||||
}
|
||||
|
||||
$imageOnly = false;
|
||||
$imageOnly = true;
|
||||
|
||||
$backgroundType = static::extractBackgroundType($data);
|
||||
$period = static::extractPeriod($data);
|
||||
$showLegend = static::extractShowLegend($data);
|
||||
$customGraphId = static::extractCustomGraphId($data);
|
||||
$graphType = static::extractGraphType($data);
|
||||
$linkedModule = static::extractLinkedModule($data);
|
||||
|
@ -205,21 +314,26 @@ final class ModuleGraph extends Item
|
|||
* the height of one of it to replicate the legacy functionality.
|
||||
*/
|
||||
|
||||
$width = (int) $data['width'];
|
||||
$height = (int) $data['height'];
|
||||
|
||||
// Custom graph.
|
||||
if (empty($customGraphId) === false) {
|
||||
$customGraph = \db_get_row('tgraph', 'id_graph', $customGraphId);
|
||||
|
||||
$params = [
|
||||
'period' => $period,
|
||||
'width' => (int) $data['width'],
|
||||
'height' => ($data['height'] - 30),
|
||||
'title' => '',
|
||||
'unit_name' => null,
|
||||
'show_alerts' => false,
|
||||
'only_image' => $imageOnly,
|
||||
'vconsole' => true,
|
||||
'document_ready' => false,
|
||||
'backgroundColor' => $backgroundType,
|
||||
'period' => $period,
|
||||
'width' => $width,
|
||||
'height' => $height,
|
||||
'title' => '',
|
||||
'unit_name' => null,
|
||||
'show_alerts' => false,
|
||||
'only_image' => $imageOnly,
|
||||
'vconsole' => true,
|
||||
'backgroundColor' => $backgroundType,
|
||||
'return_img_base_64' => true,
|
||||
'show_legend' => true,
|
||||
'show_title' => false,
|
||||
];
|
||||
|
||||
$paramsCombined = [
|
||||
|
@ -230,7 +344,8 @@ final class ModuleGraph extends Item
|
|||
'modules_series' => $customGraph['modules_series'],
|
||||
];
|
||||
|
||||
$data['html'] = \graphic_combined_module(
|
||||
$imgbase64 = 'data:image/jpg;base64,';
|
||||
$imgbase64 .= \graphic_combined_module(
|
||||
false,
|
||||
$params,
|
||||
$paramsCombined
|
||||
|
@ -242,24 +357,30 @@ final class ModuleGraph extends Item
|
|||
}
|
||||
|
||||
$params = [
|
||||
'agent_module_id' => $moduleId,
|
||||
'period' => $period,
|
||||
'show_events' => false,
|
||||
'width' => (int) $data['width'],
|
||||
'height' => ($data['height'] - 30),
|
||||
'title' => \modules_get_agentmodule_name($moduleId),
|
||||
'unit' => \modules_get_unit($moduleId),
|
||||
'only_image' => $imageOnly,
|
||||
'menu' => false,
|
||||
'backgroundColor' => $backgroundType,
|
||||
'type_graph' => $graphType,
|
||||
'vconsole' => true,
|
||||
'document_ready' => false,
|
||||
'agent_module_id' => $moduleId,
|
||||
'period' => $period,
|
||||
'show_events' => false,
|
||||
'width' => $width,
|
||||
'height' => $height,
|
||||
'title' => \modules_get_agentmodule_name(
|
||||
$moduleId
|
||||
),
|
||||
'unit' => \modules_get_unit($moduleId),
|
||||
'only_image' => $imageOnly,
|
||||
'menu' => false,
|
||||
'backgroundColor' => $backgroundType,
|
||||
'type_graph' => $graphType,
|
||||
'vconsole' => true,
|
||||
'return_img_base_64' => true,
|
||||
'show_legend' => $showLegend,
|
||||
'show_title' => false,
|
||||
];
|
||||
|
||||
$data['html'] = \grafico_modulo_sparse($params);
|
||||
$imgbase64 = 'data:image/jpg;base64,';
|
||||
$imgbase64 .= \grafico_modulo_sparse($params);
|
||||
}
|
||||
|
||||
$data['html'] = $imgbase64;
|
||||
// Restore connection.
|
||||
if ($nodeConnected === true) {
|
||||
\metaconsole_restore_db();
|
||||
|
@ -269,4 +390,260 @@ final class ModuleGraph extends Item
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return List custom graph.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getListCustomGraph():array
|
||||
{
|
||||
include_once 'include/functions_custom_graphs.php';
|
||||
enterprise_include_once('include/functions_metaconsole.php');
|
||||
$data = [];
|
||||
if (is_metaconsole() === true) {
|
||||
$data = metaconsole_get_custom_graphs(true);
|
||||
} else {
|
||||
$data = custom_graphs_get_user(
|
||||
$config['id_user'],
|
||||
false,
|
||||
true,
|
||||
'RR'
|
||||
);
|
||||
}
|
||||
|
||||
$data[0] = __('None');
|
||||
|
||||
return array_reverse($data);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Generates inputs for form (specific).
|
||||
*
|
||||
* @param array $values Default values.
|
||||
*
|
||||
* @return array Of inputs.
|
||||
*
|
||||
* @throws Exception On error.
|
||||
*/
|
||||
public static function getFormInputs(array $values): array
|
||||
{
|
||||
// Default values.
|
||||
$values = static::getDefaultGeneralValues($values);
|
||||
|
||||
// Retrieve global - common inputs.
|
||||
$inputs = Item::getFormInputs($values);
|
||||
|
||||
if (is_array($inputs) !== true) {
|
||||
throw new Exception(
|
||||
'[ModuleGraph]::getFormInputs parent class return is not an array'
|
||||
);
|
||||
}
|
||||
|
||||
if ($values['tabSelected'] === 'specific') {
|
||||
// Default values.
|
||||
if (isset($values['period']) === false) {
|
||||
$values['period'] = 3600;
|
||||
}
|
||||
|
||||
// Background color.
|
||||
$fields = [
|
||||
'white' => __('White'),
|
||||
'black' => __('Black'),
|
||||
'transparent' => __('Transparent'),
|
||||
];
|
||||
|
||||
$inputs[] = [
|
||||
'label' => __('Background color'),
|
||||
'arguments' => [
|
||||
'type' => 'select',
|
||||
'fields' => $fields,
|
||||
'name' => 'backgroundType',
|
||||
'selected' => $values['backgroundType'],
|
||||
'return' => true,
|
||||
'sort' => false,
|
||||
],
|
||||
];
|
||||
|
||||
$hiddenModule = false;
|
||||
$hiddenCustom = true;
|
||||
$checkedModule = true;
|
||||
$checkedCustom = false;
|
||||
if (isset($values['customGraphId']) === true
|
||||
&& $values['customGraphId'] !== 0
|
||||
) {
|
||||
$hiddenModule = true;
|
||||
$hiddenCustom = false;
|
||||
$checkedModule = false;
|
||||
$checkedCustom = true;
|
||||
}
|
||||
|
||||
// Choose Type module graph if graph normal or custom.
|
||||
$inputs[] = [
|
||||
'wrapper' => 'div',
|
||||
'class' => 'flex-row-vcenter',
|
||||
'direct' => 1,
|
||||
'block_content' => [
|
||||
[
|
||||
'label' => __('Module Graph'),
|
||||
'arguments' => [
|
||||
'type' => 'radio_button',
|
||||
'attributes' => 'class="btn"',
|
||||
'name' => 'choosetype',
|
||||
'value' => 'module',
|
||||
'checkedvalue' => $checkedModule,
|
||||
'script' => 'typeModuleGraph(\'module\')',
|
||||
'return' => true,
|
||||
],
|
||||
],
|
||||
[
|
||||
'label' => __('Custom Graph'),
|
||||
'arguments' => [
|
||||
'type' => 'radio_button',
|
||||
'attributes' => 'class="btn"',
|
||||
'name' => 'choosetype',
|
||||
'value' => 'custom',
|
||||
'checkedvalue' => $checkedCustom,
|
||||
'script' => 'typeModuleGraph(\'custom\')',
|
||||
'return' => true,
|
||||
],
|
||||
],
|
||||
],
|
||||
];
|
||||
|
||||
// Autocomplete agents.
|
||||
$inputs[] = [
|
||||
'id' => 'MGautoCompleteAgent',
|
||||
'hidden' => $hiddenModule,
|
||||
'label' => __('Agent'),
|
||||
'arguments' => [
|
||||
'type' => 'autocomplete_agent',
|
||||
'name' => 'agentAlias',
|
||||
'id_agent_hidden' => $values['agentId'],
|
||||
'name_agent_hidden' => 'agentId',
|
||||
'server_id_hidden' => $values['metaconsoleId'],
|
||||
'name_server_hidden' => 'metaconsoleId',
|
||||
'return' => true,
|
||||
'module_input' => true,
|
||||
'module_name' => 'moduleId',
|
||||
'module_none' => false,
|
||||
],
|
||||
];
|
||||
|
||||
// Autocomplete module.
|
||||
$inputs[] = [
|
||||
'id' => 'MGautoCompleteModule',
|
||||
'hidden' => $hiddenModule,
|
||||
'label' => __('Module'),
|
||||
'arguments' => [
|
||||
'type' => 'autocomplete_module',
|
||||
'fields' => $fields,
|
||||
'name' => 'moduleId',
|
||||
'selected' => $values['moduleId'],
|
||||
'return' => true,
|
||||
'sort' => false,
|
||||
'agent_id' => $values['agentId'],
|
||||
'metaconsole_id' => $values['metaconsoleId'],
|
||||
],
|
||||
];
|
||||
|
||||
// Custom graph.
|
||||
$fields = self::getListCustomGraph();
|
||||
$inputs[] = [
|
||||
'id' => 'MGcustomGraph',
|
||||
'hidden' => $hiddenCustom,
|
||||
'label' => __('Custom graph'),
|
||||
'arguments' => [
|
||||
'type' => 'select',
|
||||
'fields' => $fields,
|
||||
'name' => 'customGraphId',
|
||||
'selected' => $values['customGraphId'],
|
||||
'return' => true,
|
||||
],
|
||||
];
|
||||
|
||||
// Period.
|
||||
$inputs[] = [
|
||||
'label' => __('Period'),
|
||||
'arguments' => [
|
||||
'name' => 'period',
|
||||
'type' => 'interval',
|
||||
'value' => $values['period'],
|
||||
'nothing' => __('None'),
|
||||
'nothing_value' => 0,
|
||||
],
|
||||
];
|
||||
|
||||
// Graph Type.
|
||||
$fields = [
|
||||
'line' => __('Line'),
|
||||
'area' => __('Area'),
|
||||
];
|
||||
|
||||
$inputs[] = [
|
||||
'id' => 'MGgraphType',
|
||||
'hidden' => $hiddenModule,
|
||||
'label' => __('Graph Type'),
|
||||
'arguments' => [
|
||||
'type' => 'select',
|
||||
'fields' => $fields,
|
||||
'name' => 'graphType',
|
||||
'selected' => $values['graphType'],
|
||||
'return' => true,
|
||||
],
|
||||
];
|
||||
|
||||
// Show legend.
|
||||
$inputs[] = [
|
||||
'id' => 'MGshowLegend',
|
||||
'hidden' => $hiddenModule,
|
||||
'label' => __('Show legend'),
|
||||
'arguments' => [
|
||||
'name' => 'showLegend',
|
||||
'id' => 'showLegend',
|
||||
'type' => 'switch',
|
||||
'value' => $values['showLegend'],
|
||||
],
|
||||
];
|
||||
|
||||
// Inputs LinkedVisualConsole.
|
||||
$inputsLinkedVisualConsole = self::inputsLinkedVisualConsole(
|
||||
$values
|
||||
);
|
||||
foreach ($inputsLinkedVisualConsole as $key => $value) {
|
||||
$inputs[] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
return $inputs;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Default values.
|
||||
*
|
||||
* @param array $values Array values.
|
||||
*
|
||||
* @return array Array with default values.
|
||||
*
|
||||
* @overrides Item->getDefaultGeneralValues.
|
||||
*/
|
||||
public function getDefaultGeneralValues(array $values): array
|
||||
{
|
||||
// Retrieve global - common inputs.
|
||||
$values = parent::getDefaultGeneralValues($values);
|
||||
|
||||
// Default values.
|
||||
if (isset($values['width']) === false) {
|
||||
$values['width'] = 300;
|
||||
}
|
||||
|
||||
if (isset($values['height']) === false) {
|
||||
$values['height'] = 180;
|
||||
}
|
||||
|
||||
return $values;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -28,6 +28,165 @@ final class Percentile extends Item
|
|||
protected static $useLinkedVisualConsole = true;
|
||||
|
||||
|
||||
/**
|
||||
* Encode type item.
|
||||
*
|
||||
* @param array $data Data for encode.
|
||||
*
|
||||
* @return string Return 'PERCENTILE_BAR', 'PERCENTILE_BUBBLE',
|
||||
* 'CIRCULAR_PROGRESS_BAR' or 'CIRCULAR_INTERIOR_PROGRESS_BAR'.
|
||||
* 'PERCENTILE_BAR' by default.
|
||||
*/
|
||||
protected function encodePercentileType(array $data): ?int
|
||||
{
|
||||
$type = null;
|
||||
if (isset($data['percentileType']) === true) {
|
||||
switch ($data['percentileType']) {
|
||||
case 'bubble':
|
||||
$type = PERCENTILE_BUBBLE;
|
||||
break;
|
||||
|
||||
case 'circular-progress-bar':
|
||||
$type = CIRCULAR_PROGRESS_BAR;
|
||||
break;
|
||||
|
||||
case 'circular-progress-bar-alt':
|
||||
$type = CIRCULAR_INTERIOR_PROGRESS_BAR;
|
||||
break;
|
||||
|
||||
default:
|
||||
case 'progress-bar':
|
||||
$type = PERCENTILE_BAR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return $type;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Encode type item.
|
||||
*
|
||||
* @param array $data Data for encode.
|
||||
*
|
||||
* @return string Return 'PERCENTILE_BAR', 'PERCENTILE_BUBBLE',
|
||||
* 'CIRCULAR_PROGRESS_BAR' or 'CIRCULAR_INTERIOR_PROGRESS_BAR'.
|
||||
* 'PERCENTILE_BAR' by default.
|
||||
*/
|
||||
protected function encodeValueType(array $data): ?string
|
||||
{
|
||||
$valueType = null;
|
||||
if (isset($data['valueType']) === true) {
|
||||
switch ($data['valueType']) {
|
||||
case 'percent':
|
||||
case 'value':
|
||||
$valueType = $data['valueType'];
|
||||
break;
|
||||
|
||||
default:
|
||||
$valueType = 'percent';
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return $valueType;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Encode type item.
|
||||
*
|
||||
* @param array $data Data for encode.
|
||||
*
|
||||
* @return string Return 'PERCENTILE_BAR', 'PERCENTILE_BUBBLE',
|
||||
* 'CIRCULAR_PROGRESS_BAR' or 'CIRCULAR_INTERIOR_PROGRESS_BAR'.
|
||||
* 'PERCENTILE_BAR' by default.
|
||||
*/
|
||||
protected function encodeLabelColor(array $data): ?string
|
||||
{
|
||||
$labelColor = null;
|
||||
if (isset($data['labelColor']) === true) {
|
||||
$labelColor = $data['labelColor'];
|
||||
}
|
||||
|
||||
return $labelColor;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Encode type item.
|
||||
*
|
||||
* @param array $data Data for encode.
|
||||
*
|
||||
* @return string Return 'PERCENTILE_BAR', 'PERCENTILE_BUBBLE',
|
||||
* 'CIRCULAR_PROGRESS_BAR' or 'CIRCULAR_INTERIOR_PROGRESS_BAR'.
|
||||
* 'PERCENTILE_BAR' by default.
|
||||
*/
|
||||
protected function encodeColor(array $data): ?string
|
||||
{
|
||||
$color = null;
|
||||
if (isset($data['color']) === true) {
|
||||
$color = $data['color'];
|
||||
}
|
||||
|
||||
return $color;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return a valid representation of a record in database.
|
||||
*
|
||||
* @param array $data Input data.
|
||||
*
|
||||
* @return array Data structure representing a record in database.
|
||||
*
|
||||
* @overrides Item->encode.
|
||||
*/
|
||||
protected function encode(array $data): array
|
||||
{
|
||||
$return = parent::encode($data);
|
||||
|
||||
$max_value = static::parseIntOr(
|
||||
static::issetInArray($data, ['maxValue']),
|
||||
null
|
||||
);
|
||||
if ($max_value !== null) {
|
||||
$return['height'] = $max_value;
|
||||
}
|
||||
|
||||
$min_value = static::parseIntOr(
|
||||
static::issetInArray($data, ['minValue']),
|
||||
null
|
||||
);
|
||||
if ($min_value !== null) {
|
||||
$return['border_width'] = $min_value;
|
||||
}
|
||||
|
||||
$percentileType = static::encodePercentileType($data);
|
||||
if ($percentileType !== null) {
|
||||
$return['type'] = (int) $percentileType;
|
||||
}
|
||||
|
||||
$valueType = static::encodeValueType($data);
|
||||
if ($valueType !== null) {
|
||||
$return['image'] = (string) $valueType;
|
||||
}
|
||||
|
||||
$color = static::encodeColor($data);
|
||||
if ($border_color !== null) {
|
||||
$return['border_color'] = $color;
|
||||
}
|
||||
|
||||
$labelColor = static::encodeLabelColor($data);
|
||||
if ($labelColor !== null) {
|
||||
$return['fill_color'] = $labelColor;
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns a valid representation of the model.
|
||||
*
|
||||
|
@ -40,12 +199,11 @@ final class Percentile extends Item
|
|||
protected function decode(array $data): array
|
||||
{
|
||||
$return = parent::decode($data);
|
||||
$return['type'] = PERCENTILE_BAR;
|
||||
$return['type'] = (int) $data['type'];
|
||||
$return['percentileType'] = static::extractPercentileType($data);
|
||||
$return['valueType'] = static::extractValueType($data);
|
||||
// TODO: Add min value to the database.
|
||||
$return['minValue'] = static::parseFloatOr(
|
||||
static::issetInArray($data, ['minValue']),
|
||||
static::issetInArray($data, ['minValue', 'border_width']),
|
||||
null
|
||||
);
|
||||
$return['maxValue'] = static::parseFloatOr(
|
||||
|
@ -200,37 +358,45 @@ final class Percentile extends Item
|
|||
// Get the value type.
|
||||
$valueType = static::extractValueType($data);
|
||||
|
||||
if ($moduleId === null) {
|
||||
throw new \InvalidArgumentException('missing module Id');
|
||||
}
|
||||
if ($moduleId !== null && $moduleId !== 0) {
|
||||
// Maybe connect to node.
|
||||
$nodeConnected = false;
|
||||
if (\is_metaconsole() === true && $metaconsoleId !== null) {
|
||||
$nodeConnected = \metaconsole_connect(
|
||||
null,
|
||||
$metaconsoleId
|
||||
) === NOERR;
|
||||
|
||||
// Maybe connect to node.
|
||||
$nodeConnected = false;
|
||||
if (\is_metaconsole() === true && $metaconsoleId !== null) {
|
||||
$nodeConnected = \metaconsole_connect(
|
||||
null,
|
||||
$metaconsoleId
|
||||
) === NOERR;
|
||||
if ($nodeConnected === false) {
|
||||
throw new \InvalidArgumentException(
|
||||
'error connecting to the node'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if ($nodeConnected === false) {
|
||||
$moduleValue = \modules_get_last_value($moduleId);
|
||||
if ($moduleValue === false) {
|
||||
throw new \InvalidArgumentException(
|
||||
'error connecting to the node'
|
||||
'error fetching the module value'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
$moduleValue = \modules_get_last_value($moduleId);
|
||||
if ($moduleValue === false) {
|
||||
throw new \InvalidArgumentException(
|
||||
'error fetching the module value'
|
||||
);
|
||||
} else {
|
||||
$moduleValue = 0;
|
||||
}
|
||||
|
||||
// Store the module value.
|
||||
$data['value'] = (float) \number_format((float) $moduleValue, (int) $config['graph_precision'], '.', '');
|
||||
$unit = \modules_get_unit($moduleId);
|
||||
if (empty($unit) === false) {
|
||||
$data['unit'] = \io_safe_output($unit);
|
||||
$data['value'] = (float) \number_format(
|
||||
(float) $moduleValue,
|
||||
(int) $config['graph_precision'],
|
||||
'.',
|
||||
''
|
||||
);
|
||||
$unit = '';
|
||||
if ($moduleId !== null && $moduleId !== 0) {
|
||||
$unit = \modules_get_unit($moduleId);
|
||||
if (empty($unit) === false) {
|
||||
$data['unit'] = \io_safe_output($unit);
|
||||
}
|
||||
}
|
||||
|
||||
// Restore connection.
|
||||
|
@ -242,4 +408,197 @@ final class Percentile extends Item
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
* Generates inputs for form (specific).
|
||||
*
|
||||
* @param array $values Default values.
|
||||
*
|
||||
* @return array Of inputs.
|
||||
*
|
||||
* @throws Exception On error.
|
||||
*/
|
||||
public static function getFormInputs(array $values): array
|
||||
{
|
||||
// Default values.
|
||||
$values = static::getDefaultGeneralValues($values);
|
||||
|
||||
// Retrieve global - common inputs.
|
||||
$inputs = Item::getFormInputs($values);
|
||||
|
||||
if (is_array($inputs) !== true) {
|
||||
throw new Exception(
|
||||
'[Percentile]::getFormInputs parent class return is not an array'
|
||||
);
|
||||
}
|
||||
|
||||
// Default specific values.
|
||||
if (isset($values['color']) === false) {
|
||||
$values['color'] = '#000000';
|
||||
}
|
||||
|
||||
if (isset($values['labelColor']) === false) {
|
||||
$values['labelColor'] = '#bcbcbc';
|
||||
}
|
||||
|
||||
if (isset($values['percentileType']) === false) {
|
||||
$values['percentileType'] = 'circular-progress-bar';
|
||||
}
|
||||
|
||||
if ($values['tabSelected'] === 'specific') {
|
||||
// Type percentile.
|
||||
$fields = [
|
||||
'progress-bar' => __('Percentile'),
|
||||
'bubble' => __('Bubble'),
|
||||
'circular-progress-bar' => __('Circular porgress bar'),
|
||||
'circular-progress-bar-alt' => __(
|
||||
'Circular progress bar (interior)'
|
||||
),
|
||||
];
|
||||
|
||||
$inputs[] = [
|
||||
'label' => __('Type'),
|
||||
'arguments' => [
|
||||
'type' => 'select',
|
||||
'fields' => $fields,
|
||||
'name' => 'percentileType',
|
||||
'selected' => $values['percentileType'],
|
||||
'return' => true,
|
||||
'sort' => false,
|
||||
],
|
||||
];
|
||||
|
||||
// Min Value.
|
||||
$inputs[] = [
|
||||
'label' => __('Min. Value'),
|
||||
'arguments' => [
|
||||
'name' => 'minValue',
|
||||
'type' => 'number',
|
||||
'value' => $values['minValue'],
|
||||
'return' => true,
|
||||
'min' => 0,
|
||||
],
|
||||
];
|
||||
|
||||
// Max Value.
|
||||
$inputs[] = [
|
||||
'label' => __('Max. Value'),
|
||||
'arguments' => [
|
||||
'name' => 'maxValue',
|
||||
'type' => 'number',
|
||||
'value' => $values['maxValue'],
|
||||
'return' => true,
|
||||
'min' => 0,
|
||||
],
|
||||
];
|
||||
|
||||
// Value to show.
|
||||
$fields = [
|
||||
'percent' => __('Percent'),
|
||||
'value' => __('Value'),
|
||||
];
|
||||
|
||||
$inputs[] = [
|
||||
'label' => __('Value to show'),
|
||||
'arguments' => [
|
||||
'type' => 'select',
|
||||
'fields' => $fields,
|
||||
'name' => 'valueType',
|
||||
'selected' => $values['valueType'],
|
||||
'return' => true,
|
||||
'sort' => false,
|
||||
],
|
||||
];
|
||||
|
||||
// Element color.
|
||||
$inputs[] = [
|
||||
'label' => __('Element color'),
|
||||
'arguments' => [
|
||||
'wrapper' => 'div',
|
||||
'name' => 'color',
|
||||
'type' => 'color',
|
||||
'value' => $values['color'],
|
||||
'return' => true,
|
||||
],
|
||||
];
|
||||
|
||||
// Value color.
|
||||
$inputs[] = [
|
||||
'label' => __('Value color'),
|
||||
'arguments' => [
|
||||
'wrapper' => 'div',
|
||||
'name' => 'labelColor',
|
||||
'type' => 'color',
|
||||
'value' => $values['labelColor'],
|
||||
'return' => true,
|
||||
],
|
||||
];
|
||||
|
||||
// Autocomplete agents.
|
||||
$inputs[] = [
|
||||
'label' => __('Agent'),
|
||||
'arguments' => [
|
||||
'type' => 'autocomplete_agent',
|
||||
'name' => 'agentAlias',
|
||||
'id_agent_hidden' => $values['agentId'],
|
||||
'name_agent_hidden' => 'agentId',
|
||||
'server_id_hidden' => $values['metaconsoleId'],
|
||||
'name_server_hidden' => 'metaconsoleId',
|
||||
'return' => true,
|
||||
'module_input' => true,
|
||||
'module_name' => 'moduleId',
|
||||
'module_none' => false,
|
||||
],
|
||||
];
|
||||
|
||||
// Autocomplete module.
|
||||
$inputs[] = [
|
||||
'label' => __('Module'),
|
||||
'arguments' => [
|
||||
'type' => 'autocomplete_module',
|
||||
'fields' => $fields,
|
||||
'name' => 'moduleId',
|
||||
'selected' => $values['moduleId'],
|
||||
'return' => true,
|
||||
'sort' => false,
|
||||
'agent_id' => $values['agentId'],
|
||||
'metaconsole_id' => $values['metaconsoleId'],
|
||||
],
|
||||
];
|
||||
|
||||
// Inputs LinkedVisualConsole.
|
||||
$inputsLinkedVisualConsole = self::inputsLinkedVisualConsole(
|
||||
$values
|
||||
);
|
||||
foreach ($inputsLinkedVisualConsole as $key => $value) {
|
||||
$inputs[] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
return $inputs;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Default values.
|
||||
*
|
||||
* @param array $values Array values.
|
||||
*
|
||||
* @return array Array with default values.
|
||||
*
|
||||
* @overrides Item->getDefaultGeneralValues.
|
||||
*/
|
||||
public function getDefaultGeneralValues(array $values): array
|
||||
{
|
||||
// Retrieve global - common inputs.
|
||||
$values = parent::getDefaultGeneralValues($values);
|
||||
|
||||
// Default values.
|
||||
if (isset($values['width']) === false) {
|
||||
$values['width'] = 100;
|
||||
}
|
||||
|
||||
return $values;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -52,6 +52,72 @@ final class SimpleValue extends Item
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
* Extract a Process value.
|
||||
*
|
||||
* @param array $data Unknown input data structure.
|
||||
*
|
||||
* @return string One of 'none' or 'avg' or 'max' or 'min'.
|
||||
* 'none' by default.
|
||||
*/
|
||||
private static function encodeProcessValue(array $data)
|
||||
{
|
||||
$return = static::notEmptyStringOr(
|
||||
static::issetInArray(
|
||||
$data,
|
||||
['processValue']
|
||||
),
|
||||
null
|
||||
);
|
||||
|
||||
if ($return !== null) {
|
||||
switch ($return) {
|
||||
case 'avg':
|
||||
$return = SIMPLE_VALUE_AVG;
|
||||
break;
|
||||
|
||||
case 'max':
|
||||
$return = SIMPLE_VALUE_MAX;
|
||||
break;
|
||||
|
||||
case 'min':
|
||||
$return = SIMPLE_VALUE_MIN;
|
||||
break;
|
||||
|
||||
default:
|
||||
case 'none':
|
||||
$return = SIMPLE_VALUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return a valid representation of a record in database.
|
||||
*
|
||||
* @param array $data Input data.
|
||||
*
|
||||
* @return array Data structure representing a record in database.
|
||||
*
|
||||
* @overrides Item->encode.
|
||||
*/
|
||||
protected function encode(array $data): array
|
||||
{
|
||||
$return = parent::encode($data);
|
||||
$process_value = static::encodeProcessValue($data);
|
||||
if ($process_value !== null) {
|
||||
$return['type'] = $process_value;
|
||||
} else if (isset($data['processValue']) === true) {
|
||||
$return['type'] = $data['processValue'];
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns a valid representation of the model.
|
||||
*
|
||||
|
@ -67,16 +133,12 @@ final class SimpleValue extends Item
|
|||
$return['type'] = SIMPLE_VALUE;
|
||||
$return['processValue'] = static::extractProcessValue($data);
|
||||
$return['valueType'] = static::extractValueType($data);
|
||||
$return['value'] = $data['value'];
|
||||
$return['value'] = \io_safe_output($data['value']);
|
||||
|
||||
if ($return['processValue'] !== 'none') {
|
||||
$return['period'] = static::extractPeriod($data);
|
||||
}
|
||||
|
||||
// Clear the size, as this element always have a dynamic size.
|
||||
$return['width'] = 0;
|
||||
$return['height'] = 0;
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
|
@ -90,7 +152,7 @@ final class SimpleValue extends Item
|
|||
*/
|
||||
private static function extractProcessValue(array $data): string
|
||||
{
|
||||
if (isset($data['processValue'])) {
|
||||
if (isset($data['processValue']) === true) {
|
||||
switch ($data['processValue']) {
|
||||
case 'none':
|
||||
case 'avg':
|
||||
|
@ -179,7 +241,7 @@ final class SimpleValue extends Item
|
|||
// Load side libraries.
|
||||
global $config;
|
||||
include_once $config['homedir'].'/include/functions_visual_map.php';
|
||||
if (is_metaconsole()) {
|
||||
if (\is_metaconsole()) {
|
||||
\enterprise_include_once('include/functions_metaconsole.php');
|
||||
}
|
||||
|
||||
|
@ -211,10 +273,12 @@ final class SimpleValue extends Item
|
|||
}
|
||||
|
||||
// Get the formatted value.
|
||||
$value = \visual_map_get_simple_value(
|
||||
$data['type'],
|
||||
$moduleId,
|
||||
static::extractPeriod($data)
|
||||
$value = \io_safe_output(
|
||||
\visual_map_get_simple_value(
|
||||
$data['type'],
|
||||
$moduleId,
|
||||
static::extractPeriod($data)
|
||||
)
|
||||
);
|
||||
|
||||
// Restore connection.
|
||||
|
@ -224,7 +288,7 @@ final class SimpleValue extends Item
|
|||
|
||||
// Some modules are image based. Extract the base64 image if needed.
|
||||
$matches = [];
|
||||
if (\preg_match('/src=\"(data:image.*)"/', $value, $matches) === 1) {
|
||||
if (preg_match('/src=\"(data:image.*)"/', $value, $matches) === 1) {
|
||||
$data['valueType'] = 'image';
|
||||
$data['value'] = $matches[1];
|
||||
} else {
|
||||
|
@ -236,4 +300,138 @@ final class SimpleValue extends Item
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
* Generates inputs for form (specific).
|
||||
*
|
||||
* @param array $values Default values.
|
||||
*
|
||||
* @return array Of inputs.
|
||||
*
|
||||
* @throws Exception On error.
|
||||
*/
|
||||
public static function getFormInputs(array $values): array
|
||||
{
|
||||
// Default values.
|
||||
$values = static::getDefaultGeneralValues($values);
|
||||
|
||||
// Retrieve global - common inputs.
|
||||
$inputs = Item::getFormInputs($values);
|
||||
|
||||
if (is_array($inputs) !== true) {
|
||||
throw new Exception(
|
||||
'[SimpleValue]::getFormInputs parent class return is not an array'
|
||||
);
|
||||
}
|
||||
|
||||
if ($values['tabSelected'] === 'specific') {
|
||||
// Autocomplete agents.
|
||||
$inputs[] = [
|
||||
'label' => __('Agent'),
|
||||
'arguments' => [
|
||||
'type' => 'autocomplete_agent',
|
||||
'name' => 'agentAlias',
|
||||
'id_agent_hidden' => $values['agentId'],
|
||||
'name_agent_hidden' => 'agentId',
|
||||
'server_id_hidden' => $values['metaconsoleId'],
|
||||
'name_server_hidden' => 'metaconsoleId',
|
||||
'return' => true,
|
||||
'module_input' => true,
|
||||
'module_name' => 'moduleId',
|
||||
'module_none' => false,
|
||||
],
|
||||
];
|
||||
|
||||
// Autocomplete module.
|
||||
$inputs[] = [
|
||||
'label' => __('Module'),
|
||||
'arguments' => [
|
||||
'type' => 'autocomplete_module',
|
||||
'fields' => $fields,
|
||||
'name' => 'moduleId',
|
||||
'selected' => $values['moduleId'],
|
||||
'return' => true,
|
||||
'sort' => false,
|
||||
'agent_id' => $values['agentId'],
|
||||
'metaconsole_id' => $values['metaconsoleId'],
|
||||
],
|
||||
];
|
||||
|
||||
// Process.
|
||||
$fields = [
|
||||
'none' => __('None'),
|
||||
'avg' => __('Avg Value'),
|
||||
'max' => __('Max Value'),
|
||||
'min' => __('Min Value'),
|
||||
];
|
||||
|
||||
$inputs[] = [
|
||||
'label' => __('Process'),
|
||||
'arguments' => [
|
||||
'type' => 'select',
|
||||
'fields' => $fields,
|
||||
'name' => 'processValue',
|
||||
'selected' => $values['processValue'],
|
||||
'return' => true,
|
||||
'sort' => false,
|
||||
'script' => 'simpleValuePeriod()',
|
||||
],
|
||||
];
|
||||
|
||||
$hiddenPeriod = true;
|
||||
if (isset($values['processValue']) === true
|
||||
&& $values['processValue'] !== 'none'
|
||||
) {
|
||||
$hiddenPeriod = false;
|
||||
}
|
||||
|
||||
// Period.
|
||||
$inputs[] = [
|
||||
'id' => 'SVPeriod',
|
||||
'hidden' => $hiddenPeriod,
|
||||
'label' => __('Period'),
|
||||
'arguments' => [
|
||||
'name' => 'period',
|
||||
'type' => 'interval',
|
||||
'value' => $values['period'],
|
||||
'nothing' => __('None'),
|
||||
'nothing_value' => 0,
|
||||
],
|
||||
];
|
||||
|
||||
// Inputs LinkedVisualConsole.
|
||||
$inputsLinkedVisualConsole = self::inputsLinkedVisualConsole(
|
||||
$values
|
||||
);
|
||||
foreach ($inputsLinkedVisualConsole as $key => $value) {
|
||||
$inputs[] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
return $inputs;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Default values.
|
||||
*
|
||||
* @param array $values Array values.
|
||||
*
|
||||
* @return array Array with default values.
|
||||
*
|
||||
* @overrides Item->getDefaultGeneralValues.
|
||||
*/
|
||||
public function getDefaultGeneralValues(array $values): array
|
||||
{
|
||||
// Retrieve global - common inputs.
|
||||
$values = parent::getDefaultGeneralValues($values);
|
||||
|
||||
// Default values.
|
||||
if (isset($values['label']) === false) {
|
||||
$values['label'] = '(_value_)';
|
||||
}
|
||||
|
||||
return $values;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -184,9 +184,11 @@ final class StaticGraph extends Item
|
|||
$width = (int) $data['width'];
|
||||
$height = (int) $data['height'];
|
||||
if ($width === 0 || $height === 0) {
|
||||
$sizeImage = getimagesize($config['homedir'].'/'.$imagePath);
|
||||
$data['width'] = $sizeImage[0];
|
||||
$data['height'] = $sizeImage[1];
|
||||
if (isset($imagePath) && $imagePath !== false) {
|
||||
$sizeImage = getimagesize($config['homedir'].'/'.$imagePath);
|
||||
$data['width'] = $sizeImage[0];
|
||||
$data['height'] = $sizeImage[1];
|
||||
}
|
||||
}
|
||||
|
||||
// Get last value.
|
||||
|
@ -239,4 +241,128 @@ final class StaticGraph extends Item
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
* Generates inputs for form (specific).
|
||||
*
|
||||
* @param array $values Default values.
|
||||
*
|
||||
* @return array Of inputs.
|
||||
*
|
||||
* @throws Exception On error.
|
||||
*/
|
||||
public static function getFormInputs(array $values): array
|
||||
{
|
||||
// Default values.
|
||||
$values = static::getDefaultGeneralValues($values);
|
||||
|
||||
// Retrieve global - common inputs.
|
||||
$inputs = Item::getFormInputs($values);
|
||||
|
||||
if (is_array($inputs) !== true) {
|
||||
throw new Exception(
|
||||
'[StaticGraph]::getFormInputs parent class return is not an array'
|
||||
);
|
||||
}
|
||||
|
||||
// Default values.
|
||||
if (isset($values['imageSrc']) === false) {
|
||||
$values['imageSrc'] = 'network';
|
||||
}
|
||||
|
||||
if ($values['tabSelected'] === 'specific') {
|
||||
// List images VC.
|
||||
if (isset($values['imageSrc']) === false) {
|
||||
$values['imageSrc'] = 'appliance';
|
||||
}
|
||||
|
||||
$baseUrl = ui_get_full_url('/', false, false, false);
|
||||
|
||||
$inputs[] = [
|
||||
'label' => __('Image'),
|
||||
'arguments' => [
|
||||
'type' => 'select',
|
||||
'fields' => self::getListImagesVC(),
|
||||
'name' => 'imageSrc',
|
||||
'selected' => $values['imageSrc'],
|
||||
'script' => 'imageVCChange(\''.$baseUrl.'\',\''.$values['vCId'].'\')',
|
||||
'return' => true,
|
||||
],
|
||||
];
|
||||
|
||||
$images = self::imagesElementsVC($values['imageSrc']);
|
||||
|
||||
$inputs[] = [
|
||||
'block_id' => 'image-item',
|
||||
'class' => 'flex-row flex-end w100p',
|
||||
'direct' => 1,
|
||||
'block_content' => [
|
||||
['label' => $images],
|
||||
],
|
||||
];
|
||||
|
||||
// Autocomplete agents.
|
||||
$inputs[] = [
|
||||
'label' => __('Agent'),
|
||||
'arguments' => [
|
||||
'type' => 'autocomplete_agent',
|
||||
'name' => 'agentAlias',
|
||||
'id_agent_hidden' => $values['agentId'],
|
||||
'name_agent_hidden' => 'agentId',
|
||||
'server_id_hidden' => $values['metaconsoleId'],
|
||||
'name_server_hidden' => 'metaconsoleId',
|
||||
'return' => true,
|
||||
'module_input' => true,
|
||||
'module_name' => 'moduleId',
|
||||
'module_none' => true,
|
||||
],
|
||||
];
|
||||
|
||||
// Autocomplete module.
|
||||
$inputs[] = [
|
||||
'label' => __('Module'),
|
||||
'arguments' => [
|
||||
'type' => 'autocomplete_module',
|
||||
'fields' => $fields,
|
||||
'name' => 'moduleId',
|
||||
'selected' => $values['moduleId'],
|
||||
'return' => true,
|
||||
'sort' => false,
|
||||
'agent_id' => $values['agentId'],
|
||||
'metaconsole_id' => $values['metaconsoleId'],
|
||||
'nothing' => '--',
|
||||
'nothing_value' => 0,
|
||||
],
|
||||
];
|
||||
|
||||
// Show Last Value.
|
||||
$fields = [
|
||||
'default' => __('Hide last value on boolean modules'),
|
||||
'disabled' => __('Disabled'),
|
||||
'enabled' => __('Enabled'),
|
||||
];
|
||||
|
||||
$inputs[] = [
|
||||
'label' => __('Show Last Value'),
|
||||
'arguments' => [
|
||||
'type' => 'select',
|
||||
'fields' => $fields,
|
||||
'name' => 'showLastValueTooltip',
|
||||
'selected' => $values['showLastValueTooltip'],
|
||||
'return' => true,
|
||||
],
|
||||
];
|
||||
|
||||
// Inputs LinkedVisualConsole.
|
||||
$inputsLinkedVisualConsole = self::inputsLinkedVisualConsole(
|
||||
$values
|
||||
);
|
||||
foreach ($inputsLinkedVisualConsole as $key => $value) {
|
||||
$inputs[] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
return $inputs;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,596 @@
|
|||
<?php
|
||||
/**
|
||||
* Class to handle visual console interface (modals and any stuff).
|
||||
*
|
||||
* @category Class
|
||||
* @package Pandora FMS
|
||||
* @subpackage Visual Console - View
|
||||
* @version 1.0.0
|
||||
* @license See below
|
||||
*
|
||||
* ______ ___ _______ _______ ________
|
||||
* | __ \.-----.--.--.--| |.-----.----.-----. | ___| | | __|
|
||||
* | __/| _ | | _ || _ | _| _ | | ___| |__ |
|
||||
* |___| |___._|__|__|_____||_____|__| |___._| |___| |__|_|__|_______|
|
||||
*
|
||||
* ============================================================================
|
||||
* Copyright (c) 2005-2019 Artica Soluciones Tecnologicas
|
||||
* Please see http://pandorafms.org for full contribution list
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation for version 2.
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
* ============================================================================
|
||||
*/
|
||||
|
||||
// Begin.
|
||||
namespace Models\VisualConsole;
|
||||
use Models\VisualConsole\Container as VisualConsole;
|
||||
|
||||
global $config;
|
||||
require_once $config['homedir'].'/include/class/HTML.class.php';
|
||||
enterprise_include_once('include/functions_metaconsole.php');
|
||||
|
||||
/**
|
||||
* Global HTML generic class.
|
||||
*/
|
||||
class View extends \HTML
|
||||
{
|
||||
|
||||
|
||||
/**
|
||||
* Tabs.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function loadTabs()
|
||||
{
|
||||
$type = (int) \get_parameter('type', 0);
|
||||
$itemId = (int) \get_parameter('itemId', 0);
|
||||
$vCId = (int) \get_parameter('vCId', 0);
|
||||
|
||||
$url = ui_get_full_url(false, false, false, false);
|
||||
$url .= 'ajax.php?page=include/rest-api/index';
|
||||
$url .= '&loadtabs=2';
|
||||
$url .= '&type='.$type;
|
||||
$url .= '&itemId='.$itemId;
|
||||
$url .= '&vCId='.$vCId;
|
||||
|
||||
$tabs = [
|
||||
[
|
||||
'name' => __('Label settings'),
|
||||
'id' => 'tab-label',
|
||||
'href' => $url.'&tabSelected=label',
|
||||
'img' => 'label-settings.png',
|
||||
],[
|
||||
'name' => __('General settings'),
|
||||
'id' => 'tab-general',
|
||||
'href' => $url.'&tabSelected=general',
|
||||
'img' => 'general-settings.png',
|
||||
],[
|
||||
'name' => __('Specific settings'),
|
||||
'id' => 'tab-specific',
|
||||
'href' => $url.'&tabSelected=specific',
|
||||
'img' => 'specific-settings.png',
|
||||
],
|
||||
];
|
||||
|
||||
$activetabs = 2;
|
||||
if ($type === LABEL) {
|
||||
$activetabs = 0;
|
||||
$tabs = [
|
||||
[
|
||||
'name' => __('Label settings'),
|
||||
'id' => 'tab-label',
|
||||
'href' => $url.'&tabSelected=label',
|
||||
'img' => 'zoom.png',
|
||||
],[
|
||||
'name' => __('General settings'),
|
||||
'id' => 'tab-general',
|
||||
'href' => $url.'&tabSelected=general',
|
||||
'img' => 'pencil.png',
|
||||
],
|
||||
];
|
||||
} else if ($type === LINE_ITEM) {
|
||||
$activetabs = 0;
|
||||
$tabs = [
|
||||
[
|
||||
'name' => __('Specific settings'),
|
||||
'id' => 'tab-specific',
|
||||
'href' => $url.'&tabSelected=specific',
|
||||
'img' => 'event_responses_col.png',
|
||||
],
|
||||
];
|
||||
} else if ($type === BOX_ITEM || $type === COLOR_CLOUD) {
|
||||
$activetabs = 1;
|
||||
$tabs = [
|
||||
[
|
||||
'name' => __('General settings'),
|
||||
'id' => 'tab-general',
|
||||
'href' => $url.'&tabSelected=general',
|
||||
'img' => 'pencil.png',
|
||||
],[
|
||||
'name' => __('Specific settings'),
|
||||
'id' => 'tab-specific',
|
||||
'href' => $url.'&tabSelected=specific',
|
||||
'img' => 'event_responses_col.png',
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
$result = html_print_tabs($tabs);
|
||||
|
||||
// TODO:Change other place.
|
||||
\ui_require_javascript_file('tiny_mce', 'include/javascript/tiny_mce/');
|
||||
$js = '<script>
|
||||
$(function() {
|
||||
$tabs = $( "#html-tabs" ).tabs({
|
||||
beforeLoad: function (event, ui) {
|
||||
if (ui.tab.data("loaded")) {
|
||||
event.preventDefault();
|
||||
return;
|
||||
}
|
||||
ui.ajaxSettings.cache = false;
|
||||
ui.jqXHR.done(function() {
|
||||
ui.tab.data( "loaded", true );
|
||||
});
|
||||
ui.jqXHR.fail(function () {
|
||||
ui.panel.html(
|
||||
"Couldn\'t load Data. Plz Reload Page or Try Again Later."
|
||||
);
|
||||
});
|
||||
},
|
||||
load: function( event, ui ) {
|
||||
var active = $( "#html-tabs" ).tabs( "option", "active" );
|
||||
if (active === 0 && tinyMCE.editors.length == 0) {
|
||||
// Initialice.
|
||||
tinyMCE.init({
|
||||
selector: "#textarea_label",
|
||||
theme: "advanced",
|
||||
content_css: "'.ui_get_full_url(false, false, false, false).'include/styles/pandora.css",
|
||||
theme_advanced_font_sizes:
|
||||
"4pt=.visual_font_size_4pt, " +
|
||||
"6pt=.visual_font_size_6pt, " +
|
||||
"8pt=.visual_font_size_8pt, " +
|
||||
"10pt=.visual_font_size_10pt, " +
|
||||
"12pt=.visual_font_size_12pt, " +
|
||||
"14pt=.visual_font_size_14pt, " +
|
||||
"18pt=.visual_font_size_18pt, " +
|
||||
"24pt=.visual_font_size_24pt, " +
|
||||
"28pt=.visual_font_size_28pt, " +
|
||||
"36pt=.visual_font_size_36pt, " +
|
||||
"48pt=.visual_font_size_48pt, " +
|
||||
"60pt=.visual_font_size_60pt, " +
|
||||
"72pt=.visual_font_size_72pt, " +
|
||||
"84pt=.visual_font_size_84pt, " +
|
||||
"96pt=.visual_font_size_96pt, " +
|
||||
"116pt=.visual_font_size_116pt, " +
|
||||
"128pt=.visual_font_size_128pt, " +
|
||||
"140pt=.visual_font_size_140pt, " +
|
||||
"154pt=.visual_font_size_154pt, " +
|
||||
"196pt=.visual_font_size_196pt",
|
||||
theme_advanced_toolbar_location: "top",
|
||||
theme_advanced_toolbar_align: "left",
|
||||
theme_advanced_buttons1:
|
||||
"bold,italic, |,justifyleft, justifycenter, justifyright, |, undo, redo, |, image, link, |, fontselect, forecolor, fontsizeselect, |,code",
|
||||
theme_advanced_buttons2: "",
|
||||
theme_advanced_buttons3: "",
|
||||
theme_advanced_statusbar_location: "none",
|
||||
body_class: "tinyMCEBody",
|
||||
forced_root_block : false,
|
||||
force_p_newlines : false,
|
||||
force_br_newlines : true,
|
||||
convert_newlines_to_brs : false,
|
||||
remove_linebreaks : true,
|
||||
});
|
||||
}
|
||||
},
|
||||
active: '.$activetabs.'
|
||||
});';
|
||||
$js .= '});';
|
||||
$js .= '</script>';
|
||||
|
||||
return $result.$js;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Generates a form for you <3
|
||||
*
|
||||
* @return string HTML code for Form.
|
||||
*
|
||||
* @throws \Exception On error.
|
||||
*/
|
||||
public function loadForm()
|
||||
{
|
||||
// Load desired form based on item type.
|
||||
$values = [];
|
||||
$type = get_parameter('type', null);
|
||||
$tabSelected = get_parameter('tabSelected', 'label');
|
||||
$itemId = (int) get_parameter('itemId', 0);
|
||||
$vCId = (int) \get_parameter('vCId', 0);
|
||||
|
||||
$itemClass = VisualConsole::getItemClass($type);
|
||||
|
||||
if (isset($itemClass) === false) {
|
||||
throw new \Exception(__('Item type not valid ['.$type.']'));
|
||||
}
|
||||
|
||||
if (\method_exists($itemClass, 'getFormInputs') === false) {
|
||||
throw new \Exception(
|
||||
__('Item type has no getFormInputs method ['.$type.']')
|
||||
);
|
||||
}
|
||||
|
||||
$form = [
|
||||
'action' => '#',
|
||||
'method' => 'POST',
|
||||
'id' => 'itemForm-'.$tabSelected,
|
||||
'class' => 'discovery modal',
|
||||
'extra' => 'novalidate',
|
||||
];
|
||||
|
||||
if ($itemId !== 0) {
|
||||
$item = VisualConsole::getItemFromDB($itemId);
|
||||
$values = $item->toArray();
|
||||
} else {
|
||||
$values['type'] = $type;
|
||||
}
|
||||
|
||||
$values['tabSelected'] = $tabSelected;
|
||||
$values['vCId'] = $vCId;
|
||||
|
||||
// Retrieve inputs.
|
||||
$inputs = $itemClass::getFormInputs($values);
|
||||
|
||||
// Generate Form.
|
||||
$form = $this->printForm(
|
||||
[
|
||||
'form' => $form,
|
||||
'inputs' => $inputs,
|
||||
],
|
||||
true
|
||||
);
|
||||
|
||||
return $form.$jsforms;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Process a form.
|
||||
*
|
||||
* @return string JSON response.
|
||||
*/
|
||||
public function processForm()
|
||||
{
|
||||
global $config;
|
||||
// Inserted data in new item.
|
||||
$vCId = \get_parameter('vCId', 0);
|
||||
$type = \get_parameter('type', null);
|
||||
$itemId = (int) \get_parameter('itemId', 0);
|
||||
|
||||
// Type.
|
||||
$data['type'] = $type;
|
||||
|
||||
// Page Label for each item.
|
||||
$tabLabel = (bool) \get_parameter('tabLabel', false);
|
||||
if ($tabLabel === true) {
|
||||
$data['label'] = \get_parameter('label');
|
||||
$data['labelPosition'] = \get_parameter('labelPosition');
|
||||
}
|
||||
|
||||
// Page general for each item.
|
||||
$tabGeneral = (bool) \get_parameter('tabGeneral', false);
|
||||
if ($tabGeneral === true) {
|
||||
// Size.
|
||||
$data['width'] = \get_parameter('width');
|
||||
$data['height'] = \get_parameter('height');
|
||||
|
||||
// Position.
|
||||
$data['x'] = \get_parameter('x');
|
||||
$data['y'] = \get_parameter('y');
|
||||
|
||||
// Enable link.
|
||||
$data['isLinkEnabled'] = \get_parameter_switch('isLinkEnabled');
|
||||
|
||||
// Show on top.
|
||||
$data['isOnTop'] = \get_parameter_switch('isOnTop');
|
||||
|
||||
// Parent.
|
||||
$data['parentId'] = \get_parameter('parentId');
|
||||
|
||||
// ACL.
|
||||
$data['aclGroupId'] = \get_parameter('aclGroupId');
|
||||
|
||||
// Cache.
|
||||
$data['cacheExpiration_select'] = \get_parameter(
|
||||
'cacheExpiration_select'
|
||||
);
|
||||
$data['cacheExpiration_text'] = \get_parameter(
|
||||
'cacheExpiration_text'
|
||||
);
|
||||
$data['cacheExpiration'] = \get_parameter('cacheExpiration');
|
||||
$data['cacheExpiration_units'] = \get_parameter(
|
||||
'cacheExpiration_units'
|
||||
);
|
||||
} else {
|
||||
// Only Create, settings default values if not enter tab general.
|
||||
if ($itemId === 0 && $type != LINE_ITEM) {
|
||||
$class = VisualConsole::getItemClass((int) $type);
|
||||
$data = $class::getDefaultGeneralValues($data);
|
||||
}
|
||||
}
|
||||
|
||||
// Linked other VC.
|
||||
$data['linkedLayoutId'] = \get_parameter(
|
||||
'linkedLayoutId',
|
||||
0
|
||||
);
|
||||
$data['linkedLayoutNodeId'] = \get_parameter(
|
||||
'linkedLayoutNodeId',
|
||||
0
|
||||
);
|
||||
$data['linkedLayoutStatusType'] = \get_parameter(
|
||||
'linkedLayoutStatusType',
|
||||
'default'
|
||||
);
|
||||
$data['linkedLayoutStatusTypeWeight'] = \get_parameter(
|
||||
'linkedLayoutStatusTypeWeight'
|
||||
);
|
||||
$data['linkedLayoutStatusTypeCriticalThreshold'] = \get_parameter(
|
||||
'linkedLayoutStatusTypeCriticalThreshold'
|
||||
);
|
||||
$data['linkedLayoutStatusTypeWarningThreshold'] = \get_parameter(
|
||||
'linkedLayoutStatusTypeWarningThreshold'
|
||||
);
|
||||
|
||||
// Page specific data for each item.
|
||||
switch ($type) {
|
||||
case STATIC_GRAPH:
|
||||
$data['imageSrc'] = \get_parameter('imageSrc');
|
||||
$data['agentId'] = \get_parameter('agentId');
|
||||
$data['metaconsoleId'] = \get_parameter('metaconsoleId');
|
||||
$data['moduleId'] = \get_parameter('moduleId');
|
||||
$data['showLastValueTooltip'] = \get_parameter(
|
||||
'showLastValueTooltip'
|
||||
);
|
||||
break;
|
||||
|
||||
case MODULE_GRAPH:
|
||||
$data['backgroundType'] = \get_parameter('backgroundType');
|
||||
$data['agentId'] = \get_parameter('agentId');
|
||||
$data['metaconsoleId'] = \get_parameter('metaconsoleId');
|
||||
$data['moduleId'] = \get_parameter('moduleId');
|
||||
$data['customGraphId'] = \get_parameter('customGraphId');
|
||||
$data['graphType'] = \get_parameter('graphType');
|
||||
$data['showLegend'] = \get_parameter_switch('showLegend');
|
||||
$data['period'] = \get_parameter('period');
|
||||
break;
|
||||
|
||||
case SIMPLE_VALUE:
|
||||
case SIMPLE_VALUE_MAX:
|
||||
case SIMPLE_VALUE_MIN:
|
||||
case SIMPLE_VALUE_AVG:
|
||||
$data['agentId'] = \get_parameter('agentId');
|
||||
$data['metaconsoleId'] = \get_parameter('metaconsoleId');
|
||||
$data['moduleId'] = \get_parameter('moduleId');
|
||||
$data['processValue'] = \get_parameter('processValue');
|
||||
$data['period'] = \get_parameter('period');
|
||||
// Insert line default position ball end.
|
||||
if ($itemId === 0 && empty($data['label']) === true) {
|
||||
$data['label'] = '(_value_)';
|
||||
}
|
||||
break;
|
||||
|
||||
case PERCENTILE_BAR:
|
||||
case PERCENTILE_BUBBLE:
|
||||
case CIRCULAR_PROGRESS_BAR:
|
||||
case CIRCULAR_INTERIOR_PROGRESS_BAR:
|
||||
$data['percentileType'] = \get_parameter('percentileType');
|
||||
$data['minValue'] = \get_parameter('minValue');
|
||||
$data['maxValue'] = \get_parameter('maxValue');
|
||||
$data['valueType'] = \get_parameter('valueType');
|
||||
$data['color'] = \get_parameter('color');
|
||||
$data['labelColor'] = \get_parameter('labelColor');
|
||||
$data['agentId'] = \get_parameter('agentId');
|
||||
$data['metaconsoleId'] = \get_parameter('metaconsoleId');
|
||||
$data['moduleId'] = \get_parameter('moduleId');
|
||||
break;
|
||||
|
||||
case ICON:
|
||||
$data['imageSrc'] = \get_parameter('imageSrc');
|
||||
break;
|
||||
|
||||
case GROUP_ITEM:
|
||||
$data['imageSrc'] = \get_parameter('imageSrc');
|
||||
$data['showStatistics'] = \get_parameter_switch(
|
||||
'showStatistics',
|
||||
0
|
||||
);
|
||||
$data['groupId'] = \get_parameter('groupId');
|
||||
break;
|
||||
|
||||
case BOX_ITEM:
|
||||
$data['borderColor'] = \get_parameter('borderColor');
|
||||
$data['borderWidth'] = \get_parameter('borderWidth');
|
||||
$data['fillColor'] = \get_parameter('fillColor');
|
||||
$data['fillTransparent'] = \get_parameter_switch(
|
||||
'fillTransparent'
|
||||
);
|
||||
break;
|
||||
|
||||
case LINE_ITEM:
|
||||
$data['borderColor'] = \get_parameter('borderColor');
|
||||
$data['borderWidth'] = \get_parameter('borderWidth');
|
||||
$data['isOnTop'] = \get_parameter_switch('isOnTop');
|
||||
// Insert line default position ball end.
|
||||
if ($itemId === 0) {
|
||||
$data['height'] = 100;
|
||||
$data['width'] = 100;
|
||||
}
|
||||
break;
|
||||
|
||||
case AUTO_SLA_GRAPH:
|
||||
$data['agentId'] = \get_parameter('agentId');
|
||||
$data['metaconsoleId'] = \get_parameter('metaconsoleId');
|
||||
$data['agentAlias'] = \get_parameter('agentAlias');
|
||||
$data['moduleId'] = \get_parameter('moduleId');
|
||||
$data['maxTime'] = \get_parameter('maxTime');
|
||||
break;
|
||||
|
||||
case DONUT_GRAPH:
|
||||
$data['agentId'] = \get_parameter('agentId');
|
||||
$data['metaconsoleId'] = \get_parameter('metaconsoleId');
|
||||
$data['moduleId'] = \get_parameter('moduleId');
|
||||
$data['legendBackgroundColor'] = \get_parameter(
|
||||
'legendBackgroundColor'
|
||||
);
|
||||
break;
|
||||
|
||||
case BARS_GRAPH:
|
||||
$data['backgroundColor'] = \get_parameter('backgroundColor');
|
||||
$data['typeGraph'] = \get_parameter('typeGraph');
|
||||
$data['gridColor'] = \get_parameter('gridColor');
|
||||
$data['agentId'] = \get_parameter('agentId');
|
||||
$data['metaconsoleId'] = \get_parameter('metaconsoleId');
|
||||
$data['moduleId'] = \get_parameter('moduleId');
|
||||
break;
|
||||
|
||||
case CLOCK:
|
||||
$data['clockType'] = \get_parameter('clockType');
|
||||
$data['clockFormat'] = \get_parameter('clockFormat');
|
||||
$data['width'] = \get_parameter('width');
|
||||
$data['clockTimezone'] = \get_parameter('clockTimezone');
|
||||
$data['color'] = \get_parameter('color');
|
||||
break;
|
||||
|
||||
case COLOR_CLOUD:
|
||||
$data['agentId'] = \get_parameter('agentId');
|
||||
$data['metaconsoleId'] = \get_parameter('metaconsoleId');
|
||||
$data['moduleId'] = \get_parameter('moduleId');
|
||||
$data['defaultColor'] = \get_parameter('defaultColor');
|
||||
|
||||
$rangeFrom = \get_parameter('rangeFrom');
|
||||
$rangeTo = \get_parameter('rangeTo');
|
||||
$rangeColor = \get_parameter('rangeColor');
|
||||
|
||||
$arrayRangeColor = [];
|
||||
foreach ($rangeFrom as $key => $value) {
|
||||
$arrayRangeColor[$key] = [
|
||||
'color' => $rangeColor[$key],
|
||||
'fromValue' => $value,
|
||||
'toValue' => $rangeTo[$key],
|
||||
];
|
||||
}
|
||||
|
||||
$data['colorRanges'] = $arrayRangeColor;
|
||||
break;
|
||||
|
||||
case SERVICE:
|
||||
$imageSrc = \get_parameter('imageSrc');
|
||||
if ($imageSrc === '0') {
|
||||
$imageSrc = '';
|
||||
}
|
||||
|
||||
$data['imageSrc'] = $imageSrc;
|
||||
$data['serviceId'] = \get_parameter('serviceId');
|
||||
break;
|
||||
|
||||
case LABEL:
|
||||
default:
|
||||
// Not posible.
|
||||
break;
|
||||
}
|
||||
|
||||
if (isset($itemId) === false || $itemId === 0) {
|
||||
// CreateVC.
|
||||
$class = VisualConsole::getItemClass((int) $data['type']);
|
||||
try {
|
||||
// Save the new item.
|
||||
$data['id_layout'] = $vCId;
|
||||
$itemId = $class::save($data);
|
||||
} catch (\Throwable $th) {
|
||||
// Bad params.
|
||||
http_response_code(400);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Extract data new item inserted.
|
||||
try {
|
||||
$item = VisualConsole::getItemFromDB($itemId);
|
||||
$result = $item->toArray();
|
||||
} catch (Throwable $e) {
|
||||
// Bad params.
|
||||
http_response_code(400);
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
// UpdateVC.
|
||||
try {
|
||||
$item = VisualConsole::getItemFromDB($itemId);
|
||||
} catch (Throwable $e) {
|
||||
// Bad params.
|
||||
http_response_code(400);
|
||||
return false;
|
||||
}
|
||||
|
||||
$itemData = $item->toArray();
|
||||
$itemType = $itemData['type'];
|
||||
$itemAclGroupId = $itemData['aclGroupId'];
|
||||
|
||||
// ACL.
|
||||
$aclRead = check_acl($config['id_user'], $itemAclGroupId, 'VR');
|
||||
$aclWrite = check_acl($config['id_user'], $itemAclGroupId, 'VW');
|
||||
$aclManage = check_acl($config['id_user'], $itemAclGroupId, 'VM');
|
||||
|
||||
if (!$aclRead && !$aclWrite && !$aclManage) {
|
||||
db_pandora_audit(
|
||||
'ACL Violation',
|
||||
'Trying to access visual console without group access'
|
||||
);
|
||||
http_response_code(403);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check also the group Id for the group item.
|
||||
if ($itemType === GROUP_ITEM) {
|
||||
$itemGroupId = $itemData['groupId'];
|
||||
// ACL.
|
||||
$aclRead = check_acl($config['id_user'], $itemGroupId, 'VR');
|
||||
$aclWrite = check_acl($config['id_user'], $itemGroupId, 'VW');
|
||||
$aclManage = check_acl($config['id_user'], $itemGroupId, 'VM');
|
||||
|
||||
if (!$aclRead && !$aclWrite && !$aclManage) {
|
||||
db_pandora_audit(
|
||||
'ACL Violation',
|
||||
'Trying to access visual console without group access'
|
||||
);
|
||||
http_response_code(403);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (is_array($data) === true && empty($data) === false) {
|
||||
try {
|
||||
// Save the new item.
|
||||
$data['id_layout'] = $vCId;
|
||||
$data['id'] = $itemId;
|
||||
$item->save($data);
|
||||
$result = $item->toArray();
|
||||
} catch (\Throwable $th) {
|
||||
// There is no item in the database.
|
||||
echo false;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return json_encode($result);
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,379 @@
|
|||
/*
|
||||
* Discovery css global
|
||||
*/
|
||||
|
||||
ul.bigbuttonlist {
|
||||
min-height: 200px;
|
||||
}
|
||||
|
||||
li.discovery {
|
||||
display: inline-block;
|
||||
float: left;
|
||||
width: 250px;
|
||||
margin: 15px;
|
||||
padding-bottom: 50px;
|
||||
}
|
||||
|
||||
li.discovery > a {
|
||||
text-decoration: none;
|
||||
color: #333;
|
||||
}
|
||||
li.discovery > a:hover {
|
||||
color: #000;
|
||||
}
|
||||
|
||||
li.discovery img {
|
||||
height: 90px;
|
||||
}
|
||||
|
||||
li.discovery > a label {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
div.data_container > label {
|
||||
font-family: "lato", "Open Sans", sans-serif;
|
||||
font-weight: lighter;
|
||||
}
|
||||
|
||||
div.data_container {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
text-align: center;
|
||||
padding-top: 30px;
|
||||
padding-bottom: 30px;
|
||||
}
|
||||
|
||||
div.data_container:hover {
|
||||
box-shadow: 2px 2px 10px #ddd;
|
||||
}
|
||||
|
||||
/*
|
||||
* TODO: This may be at hostdevices.css
|
||||
*/
|
||||
.texto {
|
||||
height: auto;
|
||||
text-align: center;
|
||||
}
|
||||
h1.wizard {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
h1.wizard a {
|
||||
margin-left: -20px;
|
||||
}
|
||||
h1.wizard a:hover {
|
||||
color: #fff;
|
||||
}
|
||||
#text_wizard {
|
||||
font-weight: bolder;
|
||||
text-decoration: none;
|
||||
font-size: 24px;
|
||||
}
|
||||
div.arrow_box {
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
color: #888;
|
||||
padding: 1.3em;
|
||||
margin-left: 20px;
|
||||
margin-bottom: 10px;
|
||||
padding-left: 3em;
|
||||
}
|
||||
|
||||
.arrow_box.selected {
|
||||
background: #424242;
|
||||
color: #ccc;
|
||||
}
|
||||
|
||||
.arrow_box:after {
|
||||
left: 0%;
|
||||
border-left-color: white;
|
||||
border-width: 20px;
|
||||
margin-top: -20px;
|
||||
}
|
||||
|
||||
div.arrow_box:before {
|
||||
left: 100%;
|
||||
border-left-color: #ccc;
|
||||
border-width: 20px;
|
||||
margin-top: -20px;
|
||||
}
|
||||
.arrow_box.selected:before {
|
||||
border-left-color: #424242;
|
||||
}
|
||||
|
||||
.arrow_box.selected:hover {
|
||||
color: #fff;
|
||||
}
|
||||
.arrow_box:hover {
|
||||
color: #000;
|
||||
}
|
||||
|
||||
/*
|
||||
* Breadcrum
|
||||
*/
|
||||
|
||||
#menu_tab_frame_view_bc {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
border-bottom: 2px solid #82b92e;
|
||||
max-height: 70px;
|
||||
min-height: 55px;
|
||||
width: 100%;
|
||||
padding-right: 0px;
|
||||
margin-left: 0px;
|
||||
margin-bottom: 20px;
|
||||
height: 55px;
|
||||
box-sizing: border-box;
|
||||
background-color: #fafafa;
|
||||
border-top-right-radius: 7px;
|
||||
border-top-left-radius: 7px;
|
||||
box-shadow: 0px 0px 2px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
#menu_tab_frame_view_bc .breadcrumbs_container {
|
||||
align-self: flex-start;
|
||||
}
|
||||
|
||||
.breadcrumbs_container {
|
||||
padding-top: 4px;
|
||||
text-indent: 0.25em;
|
||||
padding-left: 2.5em;
|
||||
}
|
||||
|
||||
.breadcrumb_link {
|
||||
color: #848484;
|
||||
font-size: 10pt;
|
||||
font-family: "lato-bolder", "Open Sans", sans-serif;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
span.breadcrumb_link {
|
||||
color: #d0d0d0;
|
||||
font-size: 12pt;
|
||||
}
|
||||
|
||||
.breadcrumb_link.selected {
|
||||
color: #95b750;
|
||||
}
|
||||
|
||||
.breadcrumb_link.selected:hover {
|
||||
color: #95b750;
|
||||
}
|
||||
.breadcrumb_link:hover {
|
||||
color: #95b750;
|
||||
}
|
||||
|
||||
/*
|
||||
* Discovery forms structure
|
||||
*/
|
||||
|
||||
form.discovery * {
|
||||
font-size: 10pt;
|
||||
}
|
||||
|
||||
form.discovery .label_select b {
|
||||
font-family: "lato", "Open Sans", sans-serif;
|
||||
font-weight: bolder;
|
||||
}
|
||||
|
||||
.edit_discovery_info {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
padding-top: 25px;
|
||||
}
|
||||
|
||||
.edit_discovery_input {
|
||||
align-items: center;
|
||||
margin-bottom: 25px;
|
||||
}
|
||||
|
||||
/*
|
||||
* Discovery text inputs
|
||||
*/
|
||||
|
||||
.discovery_label_hint {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
label {
|
||||
color: #343434;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.discovery_full_width_input {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
li > input[type="number"],
|
||||
li > input[type="text"],
|
||||
li > input[type="email"],
|
||||
li > input[type="password"],
|
||||
.discovery_text_input > input[type="password"],
|
||||
.discovery_text_input > input[type="text"],
|
||||
#interval_manual > input[type="text"] {
|
||||
background-color: transparent;
|
||||
border: none;
|
||||
border-radius: 0;
|
||||
border-bottom: 1px solid #ccc;
|
||||
font-family: "lato-bolder", "Open Sans", sans-serif;
|
||||
font-weight: lighter;
|
||||
padding: 0px 0px 2px 0px;
|
||||
box-sizing: border-box;
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
#interval_manual > input[type="text"] {
|
||||
width: 50px;
|
||||
margin-left: 10px;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.discovery_list_input {
|
||||
width: 100%;
|
||||
border: 1px solid #cbcbcb;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.discovery_list_input option {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.discovery_list_input option:checked {
|
||||
background: #1aab8e -webkit-linear-gradient(bottom, #7db742 0%, #7db742 100%);
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.discovery_textarea_input {
|
||||
background-color: #fbfbfb;
|
||||
padding-left: 10px;
|
||||
width: 100%;
|
||||
height: 100px;
|
||||
max-height: 100px;
|
||||
max-width: 100%;
|
||||
-webkit-box-sizing: border-box;
|
||||
-moz-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
resize: none;
|
||||
}
|
||||
|
||||
a.tip {
|
||||
margin-left: 8px;
|
||||
}
|
||||
|
||||
.inline_switch > label {
|
||||
float: right;
|
||||
}
|
||||
|
||||
.discovery_interval_select_width {
|
||||
width: 90%;
|
||||
}
|
||||
|
||||
a.ext_link {
|
||||
margin-left: 1em;
|
||||
font-size: 8pt;
|
||||
}
|
||||
|
||||
/*
|
||||
* Discovery > Wizard css global style
|
||||
*/
|
||||
ul.wizard li {
|
||||
padding-bottom: 10px;
|
||||
padding-top: 10px;
|
||||
margin-right: 1em;
|
||||
}
|
||||
|
||||
ul.wizard li > label:not(.p-switch) {
|
||||
width: auto;
|
||||
vertical-align: top;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
ul.wizard li > textarea {
|
||||
width: 600px;
|
||||
height: 15em;
|
||||
display: inline-block;
|
||||
font-family: monospace;
|
||||
}
|
||||
|
||||
.hidden {
|
||||
display: none;
|
||||
}
|
||||
|
||||
form.modal ul.wizard li.hidden {
|
||||
display: none;
|
||||
}
|
||||
|
||||
form.top-action-buttons ul.wizard {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
form.modal ul.wizard li {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
width: 90%;
|
||||
margin: 0.5em auto;
|
||||
justify-items: center;
|
||||
}
|
||||
|
||||
form.modal ul.wizard li * {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
ul.wizard li.flex-indep {
|
||||
flex: 1;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
/* Tooltip message errors*/
|
||||
div.ui-tooltip.ui-corner-all.ui-widget-shadow.ui-widget.ui-widget-content.uitooltip {
|
||||
background: grey;
|
||||
opacity: 0.9;
|
||||
border-radius: 4px;
|
||||
box-shadow: 6px 5px 9px -9px black;
|
||||
padding: 6px;
|
||||
}
|
||||
|
||||
.ui-tooltip-content {
|
||||
background: transparent;
|
||||
color: #fff;
|
||||
font-weight: bold;
|
||||
font-family: "lato-lighter", "Open Sans", sans-serif;
|
||||
letter-spacing: 0.03pt;
|
||||
font-size: 8pt;
|
||||
}
|
||||
|
||||
.arrow {
|
||||
width: 70px;
|
||||
height: 16px;
|
||||
overflow: hidden;
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
margin-left: -35px;
|
||||
bottom: -16px;
|
||||
}
|
||||
.arrow.top {
|
||||
top: -16px;
|
||||
bottom: auto;
|
||||
}
|
||||
.arrow.left {
|
||||
left: 50%;
|
||||
}
|
||||
.arrow:after {
|
||||
background: grey;
|
||||
content: "";
|
||||
position: absolute;
|
||||
left: 20px;
|
||||
top: -20px;
|
||||
width: 25px;
|
||||
height: 25px;
|
||||
box-shadow: 6px 5px 9px -9px black;
|
||||
-webkit-transform: rotate(45deg);
|
||||
-ms-transform: rotate(45deg);
|
||||
transform: rotate(45deg);
|
||||
}
|
||||
.arrow.top:after {
|
||||
bottom: -20px;
|
||||
top: auto;
|
||||
}
|
||||
/* END Tooltip message errors*/
|
|
@ -1761,9 +1761,20 @@ button.deploy,
|
|||
input.deploy {
|
||||
background-image: url(../../images/input_deploy.png);
|
||||
}
|
||||
/*#table-add-item select, #table-add-sla select {
|
||||
width: 180px;
|
||||
}*/
|
||||
|
||||
button.add-item-img,
|
||||
input.add-item-img {
|
||||
background-image: url(../../images/add.png);
|
||||
background-repeat: no-repeat;
|
||||
background-position: center;
|
||||
}
|
||||
|
||||
button.remove-item-img,
|
||||
input.remove-item-img {
|
||||
background-image: url(../../images/delete.png);
|
||||
background-repeat: no-repeat;
|
||||
background-position: center;
|
||||
}
|
||||
|
||||
/* end of classes for event priorities */
|
||||
div#main_pure {
|
||||
|
@ -2493,6 +2504,11 @@ span#plugin_description {
|
|||
text-align: left;
|
||||
padding-top: 20px;
|
||||
}
|
||||
|
||||
#tinymce.mceContentBody.tinyMCEBody {
|
||||
background-color: #ededed;
|
||||
}
|
||||
|
||||
.visual_font_size_4pt,
|
||||
.visual_font_size_4pt > em,
|
||||
.visual_font_size_4pt > strong,
|
||||
|
|
|
@ -25,15 +25,35 @@ div#vc-controls img.vc-qr {
|
|||
margin-right: 8px;
|
||||
}
|
||||
|
||||
.visual-console-edit-controls {
|
||||
#menu_tab_frame_view {
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
|
||||
#edit-vc {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.visual-console-edit-controls {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.visual-console-edit-controls > span {
|
||||
margin: 4px;
|
||||
}
|
||||
|
||||
.visual-console-copy-delete {
|
||||
margin-right: 20px;
|
||||
}
|
||||
|
||||
#edit-vc label {
|
||||
flex: inherit;
|
||||
}
|
||||
|
||||
input.vs_button_ghost {
|
||||
background-color: transparent;
|
||||
border: 1px solid #82b92e;
|
||||
|
@ -50,145 +70,156 @@ input.vs_button_ghost {
|
|||
#toolbox {
|
||||
margin-top: 13px;
|
||||
}
|
||||
input.visual_editor_button_toolbox {
|
||||
padding-right: 15px;
|
||||
padding-top: 10px;
|
||||
margin-top: 5px;
|
||||
|
||||
div#editor div#toolbox input.visual_editor_button_toolbox,
|
||||
div#edit-controls input.visual_editor_button_toolbox {
|
||||
padding-right: 20px;
|
||||
padding-top: 12px;
|
||||
padding-bottom: 12px;
|
||||
border: none;
|
||||
border-bottom: 3px solid transparent;
|
||||
padding-left: 20px;
|
||||
border-radius: initial;
|
||||
}
|
||||
|
||||
div#edit-controls button.sub:hover,
|
||||
div#edit-controls input.sub:hover {
|
||||
border: 0px;
|
||||
border-bottom: 3px solid #82b92e;
|
||||
}
|
||||
|
||||
div#edit-controls button.sub[disabled],
|
||||
div#edit-controls input.sub[disabled] {
|
||||
border-color: transparent;
|
||||
}
|
||||
|
||||
input.delete_min {
|
||||
background: #fefefe url(../../images/cross.png) no-repeat center;
|
||||
background: url(../../images/cross.png) no-repeat center;
|
||||
}
|
||||
input.delete_min[disabled] {
|
||||
background: #fefefe url(../../images/cross.disabled.png) no-repeat center;
|
||||
background: url(../../images/cross.disabled.png) no-repeat center;
|
||||
}
|
||||
input.graph_min {
|
||||
background: #fefefe url(../../images/chart_curve.png) no-repeat center;
|
||||
background: url(../../images/chart_curve.png) no-repeat center;
|
||||
}
|
||||
input.graph_min[disabled] {
|
||||
background: #fefefe url(../../images/chart_curve.disabled.png) no-repeat
|
||||
center;
|
||||
background: url(../../images/chart_curve.disabled.png) no-repeat center;
|
||||
}
|
||||
input.bars_graph_min {
|
||||
background: #fefefe url(../../images/icono-barras-arriba.png) no-repeat center;
|
||||
background: url(../../images/icono-barras-arriba.png) no-repeat center;
|
||||
}
|
||||
input.bars_graph_min[disabled] {
|
||||
background: #fefefe url(../../images/icono-barras-arriba.disabled.png)
|
||||
no-repeat center;
|
||||
background: url(../../images/icono-barras-arriba.disabled.png) no-repeat
|
||||
center;
|
||||
}
|
||||
input.percentile_min {
|
||||
background: #fefefe url(../../images/chart_bar.png) no-repeat center;
|
||||
background: url(../../images/chart_bar.png) no-repeat center;
|
||||
}
|
||||
input.percentile_min[disabled] {
|
||||
background: #fefefe url(../../images/chart_bar.disabled.png) no-repeat center;
|
||||
background: url(../../images/chart_bar.disabled.png) no-repeat center;
|
||||
}
|
||||
input.percentile_item_min {
|
||||
background: #fefefe url(../../images/percentile_item.png) no-repeat center;
|
||||
background: url(../../images/percentile_item.png) no-repeat center;
|
||||
}
|
||||
input.percentile_item_min[disabled] {
|
||||
background: #fefefe url(../../images/percentile_item.disabled.png) no-repeat
|
||||
center;
|
||||
background: url(../../images/percentile_item.disabled.png) no-repeat center;
|
||||
}
|
||||
input.auto_sla_graph_min {
|
||||
background: #fefefe url(../../images/auto_sla_graph.png) no-repeat center;
|
||||
background: url(../../images/auto_sla_graph.png) no-repeat center;
|
||||
}
|
||||
input.auto_sla_graph_min[disabled] {
|
||||
background: #fefefe url(../../images/auto_sla_graph.disabled.png) no-repeat
|
||||
center;
|
||||
background: url(../../images/auto_sla_graph.disabled.png) no-repeat center;
|
||||
}
|
||||
input.donut_graph_min {
|
||||
background: #fefefe url(../../images/icono-quesito.png) no-repeat center;
|
||||
background: url(../../images/icono-quesito.png) no-repeat center;
|
||||
}
|
||||
input.donut_graph_min[disabled] {
|
||||
background: #fefefe url(../../images/icono-quesito.disabled.png) no-repeat
|
||||
center;
|
||||
background: url(../../images/icono-quesito.disabled.png) no-repeat center;
|
||||
}
|
||||
input.binary_min {
|
||||
background: #fefefe url(../../images/binary.png) no-repeat center;
|
||||
background: url(../../images/binary.png) no-repeat center;
|
||||
}
|
||||
input.binary_min[disabled] {
|
||||
background: #fefefe url(../../images/binary.disabled.png) no-repeat center;
|
||||
background: url(../../images/binary.disabled.png) no-repeat center;
|
||||
}
|
||||
input.camera_min {
|
||||
background: #fefefe url(../../images/camera.png) no-repeat center;
|
||||
background: url(../../images/camera.png) no-repeat center;
|
||||
}
|
||||
input.camera_min[disabled] {
|
||||
background: #fefefe url(../../images/camera.disabled.png) no-repeat center;
|
||||
background: url(../../images/camera.disabled.png) no-repeat center;
|
||||
}
|
||||
input.config_min {
|
||||
background: #fefefe url(../../images/config.png) no-repeat center;
|
||||
background: url(../../images/config.png) no-repeat center;
|
||||
}
|
||||
input.config_min[disabled] {
|
||||
background: #fefefe url(../../images/config.disabled.png) no-repeat center;
|
||||
background: url(../../images/config.disabled.png) no-repeat center;
|
||||
}
|
||||
input.label_min {
|
||||
background: #fefefe url(../../images/tag_red.png) no-repeat center;
|
||||
background: url(../../images/tag_red.png) no-repeat center;
|
||||
}
|
||||
input.label_min[disabled] {
|
||||
background: #fefefe url(../../images/tag_red.disabled.png) no-repeat center;
|
||||
background: url(../../images/tag_red.disabled.png) no-repeat center;
|
||||
}
|
||||
input.icon_min {
|
||||
background: #fefefe url(../../images/photo.png) no-repeat center;
|
||||
background: url(../../images/photo.png) no-repeat center;
|
||||
}
|
||||
input.icon_min[disabled] {
|
||||
background: #fefefe url(../../images/photo.disabled.png) no-repeat center;
|
||||
background: url(../../images/photo.disabled.png) no-repeat center;
|
||||
}
|
||||
input.clock_min {
|
||||
background: #fefefe url(../../images/clock-tab.png) no-repeat center;
|
||||
background: url(../../images/clock-tab.png) no-repeat center;
|
||||
}
|
||||
input.clock_min[disabled] {
|
||||
background: #fefefe url(../../images/clock-tab.disabled.png) no-repeat center;
|
||||
background: url(../../images/clock-tab.disabled.png) no-repeat center;
|
||||
}
|
||||
input.box_item {
|
||||
background: #fefefe url(../../images/box_item.png) no-repeat center;
|
||||
background: url(../../images/box_item.png) no-repeat center;
|
||||
}
|
||||
input.box_item[disabled] {
|
||||
background: #fefefe url(../../images/box_item.disabled.png) no-repeat center;
|
||||
background: url(../../images/box_item.disabled.png) no-repeat center;
|
||||
}
|
||||
input.line_item {
|
||||
background: #fefefe url(../../images/line_item.png) no-repeat center;
|
||||
background: url(../../images/line_item.png) no-repeat center;
|
||||
}
|
||||
input.line_item[disabled] {
|
||||
background: #fefefe url(../../images/line_item.disabled.png) no-repeat center;
|
||||
background: url(../../images/line_item.disabled.png) no-repeat center;
|
||||
}
|
||||
input.copy_item {
|
||||
background: #fefefe url(../../images/copy_visualmap.png) no-repeat center;
|
||||
background: url(../../images/copy_visualmap.png) no-repeat center;
|
||||
}
|
||||
input.copy_item[disabled] {
|
||||
background: #fefefe url(../../images/copy_visualmap.disabled.png) no-repeat
|
||||
center;
|
||||
background: url(../../images/copy_visualmap.disabled.png) no-repeat center;
|
||||
}
|
||||
input.grid_min {
|
||||
background: #fefefe url(../../images/grid.png) no-repeat center;
|
||||
background: url(../../images/grid.png) no-repeat center;
|
||||
}
|
||||
input.grid_min[disabled] {
|
||||
background: #fefefe url(../../images/grid.disabled.png) no-repeat center;
|
||||
background: url(../../images/grid.disabled.png) no-repeat center;
|
||||
}
|
||||
input.save_min {
|
||||
background: #fefefe url(../../images/file.png) no-repeat center;
|
||||
background: url(../../images/file.png) no-repeat center;
|
||||
}
|
||||
input.save_min[disabled] {
|
||||
background: #fefefe url(../../images/file.disabled.png) no-repeat center;
|
||||
background: url(../../images/file.disabled.png) no-repeat center;
|
||||
}
|
||||
input.service_min {
|
||||
background: #fefefe url(../../images/box.png) no-repeat center;
|
||||
background: url(../../images/box.png) no-repeat center;
|
||||
}
|
||||
input.service_min[disabled] {
|
||||
background: #fefefe url(../../images/box.disabled.png) no-repeat center;
|
||||
background: url(../../images/box.disabled.png) no-repeat center;
|
||||
}
|
||||
|
||||
input.group_item_min {
|
||||
background: #fefefe url(../../images/group_green.png) no-repeat center;
|
||||
background: url(../../images/group_green.png) no-repeat center;
|
||||
}
|
||||
input.group_item_min[disabled] {
|
||||
background: #fefefe url(../../images/group_green.disabled.png) no-repeat
|
||||
center;
|
||||
background: url(../../images/group_green.disabled.png) no-repeat center;
|
||||
}
|
||||
input.color_cloud_min {
|
||||
background: #fefefe url(../../images/color_cloud_item.png) no-repeat center;
|
||||
background: url(../../images/color_cloud_item.png) no-repeat center;
|
||||
}
|
||||
input.color_cloud_min[disabled] {
|
||||
background: #fefefe url(../../images/color_cloud_item.disabled.png) no-repeat
|
||||
center;
|
||||
background: url(../../images/color_cloud_item.disabled.png) no-repeat center;
|
||||
}
|
||||
|
||||
div#cont {
|
||||
|
|
|
@ -13,29 +13,37 @@
|
|||
display: flex;
|
||||
-webkit-box-orient: initial;
|
||||
-webkit-box-direction: initial;
|
||||
-ms-flex-direction: initial;
|
||||
flex-direction: initial;
|
||||
-ms-flex-direction: initial;
|
||||
flex-direction: initial;
|
||||
justify-items: center;
|
||||
-webkit-box-align: center;
|
||||
-ms-flex-align: center;
|
||||
align-items: center;
|
||||
-ms-flex-align: center;
|
||||
align-items: center;
|
||||
-webkit-user-select: text;
|
||||
-moz-user-select: text;
|
||||
-ms-user-select: text;
|
||||
user-select: text;
|
||||
-moz-user-select: text;
|
||||
-ms-user-select: text;
|
||||
user-select: text;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.visual-console-item.is-on-top {
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.visual-console-item.is-editing {
|
||||
border: 2px dashed #b2b2b2;
|
||||
-webkit-transform: translateX(-2px) translateY(-2px);
|
||||
transform: translateX(-2px) translateY(-2px);
|
||||
cursor: move;
|
||||
transform: translateX(-2px) translateY(-2px);
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.visual-console-item.is-editing.is-selected {
|
||||
border: 2px dashed #2b2b2b;
|
||||
cursor: move;
|
||||
}
|
||||
.visual-console-item.is-editing > .resize-draggable {
|
||||
float: right;
|
||||
position: absolute;
|
||||
|
@ -47,6 +55,756 @@
|
|||
cursor: se-resize;
|
||||
}
|
||||
|
||||
.visual-console-item.is-editing :first-child {
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
@-webkit-keyframes spinner-loading {
|
||||
0% {
|
||||
-webkit-transform: rotate(0deg);
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
to {
|
||||
-webkit-transform: rotate(1turn);
|
||||
transform: rotate(1turn);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes spinner-loading {
|
||||
0% {
|
||||
-webkit-transform: rotate(0deg);
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
to {
|
||||
-webkit-transform: rotate(1turn);
|
||||
transform: rotate(1turn);
|
||||
}
|
||||
}
|
||||
|
||||
.visual-console-spinner {
|
||||
background-color: transparent;
|
||||
margin: 0px auto;
|
||||
border-top: 5px solid rgb(82, 85, 87);
|
||||
border-right: 5px solid rgb(82, 85, 87);
|
||||
border-bottom: 5px solid rgb(82, 85, 87);
|
||||
border-left: 5px solid rgba(82, 85, 87, 0.2);
|
||||
|
||||
-webkit-animation-name: spinner-loading;
|
||||
|
||||
animation-name: spinner-loading;
|
||||
-webkit-animation-duration: 0.8s;
|
||||
animation-duration: 0.8s;
|
||||
-webkit-animation-iteration-count: infinite;
|
||||
animation-iteration-count: infinite;
|
||||
-webkit-animation-timing-function: linear;
|
||||
animation-timing-function: linear;
|
||||
}
|
||||
|
||||
.visual-console-spinner,
|
||||
.visual-console-spinner :after {
|
||||
display: block;
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.visual-console-spinner.small,
|
||||
.visual-console-spinner.small :after {
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
}
|
||||
|
||||
.div-visual-console-spinner {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: -webkit-box;
|
||||
display: -ms-flexbox;
|
||||
display: flex;
|
||||
-webkit-box-align: center;
|
||||
-ms-flex-align: center;
|
||||
align-items: center;
|
||||
opacity: 0.7;
|
||||
background: rgb(212, 215, 218);
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.show-elements {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.hide-elements {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/*Forms*/
|
||||
.div-input-group label {
|
||||
display: -webkit-box;
|
||||
display: -ms-flexbox;
|
||||
display: flex;
|
||||
-webkit-box-orient: horizontal;
|
||||
-webkit-box-direction: normal;
|
||||
-ms-flex-direction: row;
|
||||
flex-direction: row;
|
||||
-ms-flex-wrap: wrap;
|
||||
flex-wrap: wrap;
|
||||
-webkit-box-align: center;
|
||||
-ms-flex-align: center;
|
||||
align-items: center;
|
||||
font-size: 12pt;
|
||||
font-family: "lato-bolder", "Open Sans", sans-serif;
|
||||
font-weight: 600;
|
||||
color: #343434;
|
||||
margin-right: 10px;
|
||||
}
|
||||
.div-input-group label img {
|
||||
margin-left: 4px;
|
||||
}
|
||||
|
||||
.div-input-group input[type="text"],
|
||||
.div-input-group input[type="number"] {
|
||||
height: 25px;
|
||||
font-size: 10pt;
|
||||
background-color: transparent;
|
||||
border: none;
|
||||
border-radius: 0;
|
||||
border-bottom: 1px solid #ccc;
|
||||
font-family: "lato-bolder", "Open Sans", sans-serif;
|
||||
font-weight: lighter;
|
||||
padding: 0px 0px 2px 0px;
|
||||
-webkit-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
margin-right: 10px;
|
||||
padding-left: 2px;
|
||||
}
|
||||
|
||||
.div-input-group input[type="radio"] {
|
||||
margin-right: 10px;
|
||||
width: 17px;
|
||||
height: 17px;
|
||||
}
|
||||
|
||||
.div-input-group select {
|
||||
font-family: "lato-bolder", "Open Sans", sans-serif;
|
||||
font-weight: lighter;
|
||||
font-size: 10pt;
|
||||
}
|
||||
|
||||
.input-groups {
|
||||
display: -webkit-box;
|
||||
display: -ms-flexbox;
|
||||
display: flex;
|
||||
-webkit-box-orient: vertical;
|
||||
-webkit-box-direction: normal;
|
||||
-ms-flex-direction: column;
|
||||
flex-direction: column;
|
||||
-ms-flex-wrap: wrap;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.input-group {
|
||||
width: 100%;
|
||||
margin-bottom: 25px;
|
||||
padding-left: 20px;
|
||||
}
|
||||
|
||||
.div-ranges-input-group {
|
||||
display: -webkit-box;
|
||||
display: -ms-flexbox;
|
||||
display: flex;
|
||||
-webkit-box-orient: vertical;
|
||||
-webkit-box-direction: normal;
|
||||
-ms-flex-direction: column;
|
||||
flex-direction: column;
|
||||
-ms-flex-wrap: wrap;
|
||||
flex-wrap: wrap;
|
||||
-webkit-box-align: start;
|
||||
-ms-flex-align: start;
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
.div-ranges-input-group > div {
|
||||
padding-left: 20px;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.div-input-group,
|
||||
.div-input-group div div {
|
||||
display: -webkit-box;
|
||||
display: -ms-flexbox;
|
||||
display: flex;
|
||||
-webkit-box-orient: horizontal;
|
||||
-webkit-box-direction: normal;
|
||||
-ms-flex-direction: row;
|
||||
flex-direction: row;
|
||||
-ms-flex-wrap: wrap;
|
||||
flex-wrap: wrap;
|
||||
-webkit-box-align: center;
|
||||
-ms-flex-align: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.div-input-group h3 {
|
||||
text-transform: initial;
|
||||
font-family: "lato-bolder", "Open Sans", sans-serif;
|
||||
text-align: center;
|
||||
font-style: italic;
|
||||
text-decoration: underline;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.div-input-group div div a {
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
.div-input-group-autocomplete-agent {
|
||||
display: -webkit-box;
|
||||
display: -ms-flexbox;
|
||||
display: flex;
|
||||
-webkit-box-orient: vertical;
|
||||
-webkit-box-direction: normal;
|
||||
-ms-flex-direction: column;
|
||||
flex-direction: column;
|
||||
-ms-flex-wrap: wrap;
|
||||
flex-wrap: wrap;
|
||||
-webkit-box-align: start;
|
||||
-ms-flex-align: start;
|
||||
align-items: flex-start;
|
||||
-webkit-box-pack: justify;
|
||||
-ms-flex-pack: justify;
|
||||
justify-content: space-between;
|
||||
height: 70px;
|
||||
}
|
||||
|
||||
.div-input-group-inside {
|
||||
padding-left: 20px;
|
||||
}
|
||||
|
||||
.input-group-link-console {
|
||||
height: 70px;
|
||||
}
|
||||
|
||||
.show-elements > div.div-input-group-autocomplete-agent {
|
||||
margin-left: 20px;
|
||||
}
|
||||
|
||||
.img-vc-elements {
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
input.error-input-validate[type="number"],
|
||||
input.error-input-validate[type="text"],
|
||||
select.error-input-validate {
|
||||
border: 1px solid #c00;
|
||||
}
|
||||
|
||||
select.error-input-validate:focus {
|
||||
outline-color: #c00;
|
||||
}
|
||||
|
||||
p.error-p-validate {
|
||||
width: 100%;
|
||||
color: #c00;
|
||||
}
|
||||
|
||||
/* Styles for the solid icons */
|
||||
|
||||
.fa {
|
||||
display: inline-block;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.fa,
|
||||
.fa > svg,
|
||||
.fa.medium,
|
||||
.fa.medium > svg {
|
||||
width: 28px;
|
||||
height: 28px;
|
||||
}
|
||||
|
||||
.fa.fa-small,
|
||||
.fa.fa-small > svg {
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
}
|
||||
|
||||
.fa.fa-large,
|
||||
.fa.fa-large > svg {
|
||||
width: 44px;
|
||||
height: 44px;
|
||||
}
|
||||
|
||||
.fa-spin {
|
||||
-webkit-animation: fa-spin 2s infinite linear;
|
||||
animation: fa-spin 2s infinite linear;
|
||||
}
|
||||
|
||||
.fa-pulse {
|
||||
-webkit-animation: fa-spin 1s infinite steps(8);
|
||||
animation: fa-spin 1s infinite steps(8);
|
||||
}
|
||||
|
||||
@-webkit-keyframes fa-spin {
|
||||
0% {
|
||||
-webkit-transform: rotate(0deg);
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
100% {
|
||||
-webkit-transform: rotate(360deg);
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes fa-spin {
|
||||
0% {
|
||||
-webkit-transform: rotate(0deg);
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
100% {
|
||||
-webkit-transform: rotate(360deg);
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
|
||||
.autocomplete {
|
||||
/*the container must be positioned relative:*/
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
}
|
||||
.autocomplete input {
|
||||
/*background: pink;*/
|
||||
}
|
||||
.autocomplete-items {
|
||||
border: 1px solid #d4d4d4;
|
||||
border-bottom: none;
|
||||
border-top: none;
|
||||
/*position the autocomplete items to be the same width as the container:*/
|
||||
position: absolute;
|
||||
z-index: 1;
|
||||
overflow: auto;
|
||||
max-height: 150px;
|
||||
max-width: 250px;
|
||||
}
|
||||
.autocomplete-items div {
|
||||
width: 100%;
|
||||
padding: 10px;
|
||||
cursor: pointer;
|
||||
background-color: #fff;
|
||||
border-bottom: 1px solid #d4d4d4;
|
||||
border-top: 1px solid #d4d4d4;
|
||||
}
|
||||
.autocomplete-items div:hover {
|
||||
width: 100%;
|
||||
background-color: #e9e9e9;
|
||||
}
|
||||
.autocomplete-active {
|
||||
/*when navigating through the items using the arrow keys:*/
|
||||
background-color: DodgerBlue !important;
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
/*
|
||||
@font-face {
|
||||
font-family: Alarm Clock;
|
||||
src: url(alarm-clock.ttf);
|
||||
}
|
||||
*/
|
||||
|
||||
/* Digital clock */
|
||||
|
||||
.visual-console-item .digital-clock {
|
||||
display: -webkit-box;
|
||||
display: -ms-flexbox;
|
||||
display: flex;
|
||||
-webkit-box-orient: vertical;
|
||||
-webkit-box-direction: normal;
|
||||
-ms-flex-direction: column;
|
||||
flex-direction: column;
|
||||
-webkit-box-pack: center;
|
||||
-ms-flex-pack: center;
|
||||
justify-content: center;
|
||||
justify-items: center;
|
||||
-ms-flex-line-pack: center;
|
||||
align-content: center;
|
||||
-webkit-box-align: center;
|
||||
-ms-flex-align: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.visual-console-item .digital-clock > span {
|
||||
/* To improve legibility */
|
||||
text-rendering: optimizeLegibility;
|
||||
text-shadow: rgba(0, 0, 0, 0.01) 0 0 1px;
|
||||
}
|
||||
|
||||
.visual-console-item .digital-clock > span.time {
|
||||
font-family: "Alarm Clock", "Courier New", Courier, monospace;
|
||||
font-size: 50px;
|
||||
}
|
||||
|
||||
.visual-console-item .digital-clock > span.date {
|
||||
font-family: "Alarm Clock", "Courier New", Courier, monospace;
|
||||
font-size: 25px;
|
||||
}
|
||||
|
||||
.visual-console-item .digital-clock > span.timezone {
|
||||
font-size: 25px;
|
||||
}
|
||||
|
||||
/* Analog clock */
|
||||
|
||||
.visual-console-item .analogic-clock {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.visual-console-item .analogic-clock .hour-hand {
|
||||
-webkit-animation: rotate-hour 43200s infinite linear;
|
||||
animation: rotate-hour 43200s infinite linear;
|
||||
}
|
||||
|
||||
.visual-console-item .analogic-clock .minute-hand {
|
||||
-webkit-animation: rotate-minute 3600s infinite linear;
|
||||
animation: rotate-minute 3600s infinite linear;
|
||||
}
|
||||
|
||||
.visual-console-item .analogic-clock .second-hand {
|
||||
-webkit-animation: rotate-second 60s infinite linear;
|
||||
animation: rotate-second 60s infinite linear;
|
||||
}
|
||||
|
||||
#html-tabs .ui-widget-header {
|
||||
background-color: #ffffff;
|
||||
border: 0px;
|
||||
}
|
||||
|
||||
#html-tabs .ui-tabs-anchor {
|
||||
float: none;
|
||||
display: -webkit-box;
|
||||
display: -ms-flexbox;
|
||||
display: flex;
|
||||
-webkit-box-orient: horizontal;
|
||||
-webkit-box-direction: normal;
|
||||
-ms-flex-direction: row;
|
||||
flex-direction: row;
|
||||
-webkit-box-align: center;
|
||||
-ms-flex-align: center;
|
||||
align-items: center;
|
||||
-webkit-box-pack: justify;
|
||||
-ms-flex-pack: justify;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
#html-tabs .ui-tabs-anchor img {
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
#html-tabs .ui-tabs-nav li {
|
||||
border-radius: 5px 5px 0px 0px;
|
||||
}
|
||||
|
||||
label span.p-slider {
|
||||
width: 30px;
|
||||
}
|
||||
|
||||
li.interval-color-ranges > label,
|
||||
li#li-default-ranges > label {
|
||||
margin-right: 15px;
|
||||
}
|
||||
|
||||
li.interval-color-ranges > input[type="number"],
|
||||
li#li-default-ranges > input[type="number"] {
|
||||
width: 80px;
|
||||
}
|
||||
|
||||
li.interval-color-ranges > label:not(:first-child),
|
||||
li#li-default-ranges > label:not(:first-child),
|
||||
li#li-size-item > label:not(:first-child),
|
||||
li#li-position-item > label:not(:first-child) {
|
||||
width: initial;
|
||||
margin-left: 15px;
|
||||
}
|
||||
|
||||
li#li-image-item label {
|
||||
display: -webkit-box;
|
||||
display: -ms-flexbox;
|
||||
display: flex;
|
||||
-webkit-box-orient: horizontal;
|
||||
-webkit-box-direction: normal;
|
||||
-ms-flex-direction: row;
|
||||
flex-direction: row;
|
||||
-webkit-box-pack: end;
|
||||
-ms-flex-pack: end;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
li#li-image-item label img {
|
||||
-webkit-box-flex: initial;
|
||||
-ms-flex: initial;
|
||||
flex: initial;
|
||||
}
|
||||
|
||||
.discovery.modal * {
|
||||
font-weight: normal;
|
||||
color: #343434;
|
||||
font-family: "lato", "Open Sans", sans-serif;
|
||||
}
|
||||
|
||||
.discovery.modal select {
|
||||
width: 100px;
|
||||
}
|
||||
|
||||
.discovery.modal div#period_manual select,
|
||||
.discovery.modal div#period_manual input,
|
||||
.discovery.modal div#period_default select,
|
||||
.discovery.modal div#cacheExpiration_manual select,
|
||||
.discovery.modal div#cacheExpiration_manual input,
|
||||
.discovery.modal div#cacheExpiration_default select {
|
||||
font-size: inherit !important;
|
||||
}
|
||||
.discovery.modal div#period_default select#period_select,
|
||||
.discovery.modal div#cacheExpiration_default select#cacheExpiration_select {
|
||||
max-width: 230px;
|
||||
width: inherit;
|
||||
}
|
||||
|
||||
li#li-timeZone-item > label:not(:first-child),
|
||||
.discovery.modal li#div-textarea-label > label {
|
||||
-webkit-box-flex: inherit;
|
||||
-ms-flex: inherit;
|
||||
flex: inherit;
|
||||
}
|
||||
|
||||
li#li-timeZone-item > select:not(:first-child) {
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
.discovery.modal li#div-textarea-label table tbody td.mceIframeContainer {
|
||||
background-color: #ededed;
|
||||
}
|
||||
|
||||
/*style item group show statistic*/
|
||||
.group-container {
|
||||
display: -webkit-box;
|
||||
display: -ms-flexbox;
|
||||
display: flex;
|
||||
-webkit-box-orient: vertical;
|
||||
-webkit-box-direction: normal;
|
||||
-ms-flex-direction: column;
|
||||
flex-direction: column;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
.group-container .group-item-title {
|
||||
width: 100%;
|
||||
height: 30%;
|
||||
background-color: #9d9ea0;
|
||||
color: black;
|
||||
font-weight: bold;
|
||||
display: -webkit-box;
|
||||
display: -ms-flexbox;
|
||||
display: flex;
|
||||
-webkit-box-orient: horizontal;
|
||||
-webkit-box-direction: normal;
|
||||
-ms-flex-direction: row;
|
||||
flex-direction: row;
|
||||
-webkit-box-align: center;
|
||||
-ms-flex-align: center;
|
||||
align-items: center;
|
||||
-webkit-box-pack: center;
|
||||
-ms-flex-pack: center;
|
||||
justify-content: center;
|
||||
}
|
||||
.group-container .group-item-info {
|
||||
width: 100%;
|
||||
height: 70%;
|
||||
display: -webkit-box;
|
||||
display: -ms-flexbox;
|
||||
display: flex;
|
||||
-webkit-box-orient: horizontal;
|
||||
-webkit-box-direction: normal;
|
||||
-ms-flex-direction: row;
|
||||
flex-direction: row;
|
||||
-ms-flex-wrap: wrap;
|
||||
flex-wrap: wrap;
|
||||
padding: 2%;
|
||||
-webkit-box-align: center;
|
||||
-ms-flex-align: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.group-container .group-item-info .group-item-info-container {
|
||||
-webkit-box-flex: 1;
|
||||
-ms-flex: 1 1 80px;
|
||||
flex: 1 1 80px;
|
||||
display: -webkit-box;
|
||||
display: -ms-flexbox;
|
||||
display: flex;
|
||||
-webkit-box-orient: horizontal;
|
||||
-webkit-box-direction: normal;
|
||||
-ms-flex-direction: row;
|
||||
flex-direction: row;
|
||||
border-radius: 2px;
|
||||
height: 100%;
|
||||
max-height: 50px;
|
||||
margin: 5px;
|
||||
}
|
||||
|
||||
.group-container .group-item-info .group-item-info-container .value-style {
|
||||
-webkit-box-flex: 1;
|
||||
-ms-flex: 1;
|
||||
flex: 1;
|
||||
color: #fff;
|
||||
font-size: 100%;
|
||||
padding: 5px;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: -webkit-box;
|
||||
display: -ms-flexbox;
|
||||
display: flex;
|
||||
-webkit-box-orient: horizontal;
|
||||
-webkit-box-direction: normal;
|
||||
-ms-flex-direction: row;
|
||||
flex-direction: row;
|
||||
-webkit-box-align: center;
|
||||
-ms-flex-align: center;
|
||||
align-items: center;
|
||||
-webkit-box-pack: center;
|
||||
-ms-flex-pack: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.group-container .group-item-info .group-item-info-container .name-style {
|
||||
-webkit-box-flex: 1;
|
||||
-ms-flex: 1;
|
||||
flex: 1;
|
||||
background-color: white;
|
||||
color: black;
|
||||
font-size: 100%;
|
||||
padding: 5px;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: -webkit-box;
|
||||
display: -ms-flexbox;
|
||||
display: flex;
|
||||
-webkit-box-orient: horizontal;
|
||||
-webkit-box-direction: normal;
|
||||
-ms-flex-direction: row;
|
||||
flex-direction: row;
|
||||
-webkit-box-align: center;
|
||||
-ms-flex-align: center;
|
||||
align-items: center;
|
||||
-webkit-box-pack: center;
|
||||
-ms-flex-pack: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
div.label,
|
||||
div.simple-value {
|
||||
display: inline-table;
|
||||
min-width: -webkit-fit-content;
|
||||
min-width: -moz-fit-content;
|
||||
min-width: fit-content;
|
||||
min-height: -webkit-fit-content;
|
||||
min-height: -moz-fit-content;
|
||||
min-height: fit-content;
|
||||
}
|
||||
|
||||
/* Styles for the solid icons */
|
||||
|
||||
.fa {
|
||||
display: inline-block;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.fa,
|
||||
.fa > svg,
|
||||
.fa.medium,
|
||||
.fa.medium > svg {
|
||||
width: 28px;
|
||||
height: 28px;
|
||||
}
|
||||
|
||||
.fa.fa-small,
|
||||
.fa.fa-small > svg {
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
}
|
||||
|
||||
.fa.fa-large,
|
||||
.fa.fa-large > svg {
|
||||
width: 44px;
|
||||
height: 44px;
|
||||
}
|
||||
|
||||
.fa-spin {
|
||||
-webkit-animation: fa-spin 2s infinite linear;
|
||||
animation: fa-spin 2s infinite linear;
|
||||
}
|
||||
|
||||
.fa-pulse {
|
||||
-webkit-animation: fa-spin 1s infinite steps(8);
|
||||
animation: fa-spin 1s infinite steps(8);
|
||||
}
|
||||
|
||||
@-webkit-keyframes fa-spin {
|
||||
0% {
|
||||
-webkit-transform: rotate(0deg);
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
100% {
|
||||
-webkit-transform: rotate(360deg);
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes fa-spin {
|
||||
0% {
|
||||
-webkit-transform: rotate(0deg);
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
100% {
|
||||
-webkit-transform: rotate(360deg);
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
|
||||
.autocomplete {
|
||||
/*the container must be positioned relative:*/
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
}
|
||||
.autocomplete input {
|
||||
/*background: pink;*/
|
||||
}
|
||||
.autocomplete-items {
|
||||
border: 1px solid #d4d4d4;
|
||||
border-bottom: none;
|
||||
border-top: none;
|
||||
/*position the autocomplete items to be the same width as the container:*/
|
||||
position: absolute;
|
||||
z-index: 1;
|
||||
overflow: auto;
|
||||
max-height: 150px;
|
||||
max-width: 250px;
|
||||
}
|
||||
.autocomplete-items div {
|
||||
width: 100%;
|
||||
padding: 10px;
|
||||
cursor: pointer;
|
||||
background-color: #fff;
|
||||
border-bottom: 1px solid #d4d4d4;
|
||||
border-top: 1px solid #d4d4d4;
|
||||
}
|
||||
.autocomplete-items div:hover {
|
||||
width: 100%;
|
||||
background-color: #e9e9e9;
|
||||
}
|
||||
.autocomplete-active {
|
||||
/*when navigating through the items using the arrow keys:*/
|
||||
background-color: DodgerBlue !important;
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: Alarm Clock;
|
||||
src: url(alarm-clock.ttf);
|
||||
|
@ -60,23 +818,20 @@
|
|||
display: flex;
|
||||
-webkit-box-orient: vertical;
|
||||
-webkit-box-direction: normal;
|
||||
-ms-flex-direction: column;
|
||||
flex-direction: column;
|
||||
-ms-flex-direction: column;
|
||||
flex-direction: column;
|
||||
-webkit-box-pack: center;
|
||||
-ms-flex-pack: center;
|
||||
justify-content: center;
|
||||
-ms-flex-pack: center;
|
||||
justify-content: center;
|
||||
justify-items: center;
|
||||
-ms-flex-line-pack: center;
|
||||
align-content: center;
|
||||
align-content: center;
|
||||
-webkit-box-align: center;
|
||||
-ms-flex-align: center;
|
||||
align-items: center;
|
||||
-ms-flex-align: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.visual-console-item .digital-clock > span {
|
||||
font-family: "Alarm Clock", "Courier New", Courier, monospace;
|
||||
font-size: 50px;
|
||||
|
||||
/* To improve legibility */
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
|
@ -84,12 +839,17 @@
|
|||
text-shadow: rgba(0, 0, 0, 0.01) 0 0 1px;
|
||||
}
|
||||
|
||||
.visual-console-item .digital-clock > span.time {
|
||||
font-family: "Alarm Clock", "Courier New", Courier, monospace;
|
||||
font-size: 50px;
|
||||
}
|
||||
|
||||
.visual-console-item .digital-clock > span.date {
|
||||
font-size: 25px;
|
||||
}
|
||||
|
||||
.visual-console-item .digital-clock > span.timezone {
|
||||
font-size: 28px;
|
||||
font-size: 25px;
|
||||
}
|
||||
|
||||
/* Analog clock */
|
||||
|
@ -100,17 +860,18 @@
|
|||
|
||||
.visual-console-item .analogic-clock .hour-hand {
|
||||
-webkit-animation: rotate-hour 43200s infinite linear;
|
||||
animation: rotate-hour 43200s infinite linear;
|
||||
animation: rotate-hour 43200s infinite linear;
|
||||
}
|
||||
|
||||
.visual-console-item .analogic-clock .minute-hand {
|
||||
-webkit-animation: rotate-minute 3600s infinite linear;
|
||||
animation: rotate-minute 3600s infinite linear;
|
||||
animation: rotate-minute 3600s infinite linear;
|
||||
}
|
||||
|
||||
.visual-console-item .analogic-clock .second-hand {
|
||||
-webkit-animation: rotate-second 60s infinite linear;
|
||||
animation: rotate-second 60s infinite linear;
|
||||
animation: rotate-second 60s infinite linear;
|
||||
}
|
||||
|
||||
/*# sourceMappingURL=vc.main.css.map*/
|
||||
|
||||
/*# sourceMappingURL=vc.main.css.map*/
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -95,7 +95,7 @@ page.onCallback = function() {
|
|||
page.render(output_filename, { format: "png" });
|
||||
} else {
|
||||
page.settings.loadImages = false;
|
||||
var base64 = page.renderBase64("jpg");
|
||||
var base64 = page.renderBase64("png");
|
||||
// do not remove this console.output
|
||||
console.log(base64);
|
||||
}
|
||||
|
|
|
@ -28,6 +28,8 @@ if (file_exists(ENTERPRISE_DIR.'/include/functions_login.php')) {
|
|||
|
||||
require_once $config['homedir'].'/vendor/autoload.php';
|
||||
|
||||
ui_require_css_file('visual_maps');
|
||||
|
||||
echo '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">'."\n";
|
||||
echo '<html xmlns="http://www.w3.org/1999/xhtml">'."\n";
|
||||
echo '<head>';
|
||||
|
@ -222,6 +224,9 @@ $visualConsoleItems = VisualConsole::getItemsFromDB(
|
|||
handleUpdate
|
||||
);
|
||||
|
||||
var controls = document.getElementById('vc-controls');
|
||||
autoHideElement(controls, 1000);
|
||||
|
||||
// Update the data fetch interval.
|
||||
$('select#vc-refr').change(function(event) {
|
||||
var refr = Number.parseInt(event.target.value);
|
||||
|
|
|
@ -1,25 +1,73 @@
|
|||
<?php
|
||||
/**
|
||||
* Extension to manage a list of gateways and the node address where they should
|
||||
* point to.
|
||||
*
|
||||
* @category Extensions
|
||||
* @package Pandora FMS
|
||||
* @subpackage Community
|
||||
* @version 1.0.0
|
||||
* @license See below
|
||||
*
|
||||
* ______ ___ _______ _______ ________
|
||||
* | __ \.-----.--.--.--| |.-----.----.-----. | ___| | | __|
|
||||
* | __/| _ | | _ || _ | _| _ | | ___| |__ |
|
||||
* |___| |___._|__|__|_____||_____|__| |___._| |___| |__|_|__|_______|
|
||||
*
|
||||
* ============================================================================
|
||||
* Copyright (c) 2005-2019 Artica Soluciones Tecnologicas
|
||||
* Please see http://pandorafms.org for full contribution list
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation for version 2.
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
* ============================================================================
|
||||
*/
|
||||
|
||||
// Pandora FMS - http://pandorafms.com
|
||||
// ==================================================
|
||||
// Copyright (c) 2005-2019 Artica Soluciones Tecnologicas
|
||||
// Please see http://pandorafms.org for full contribution list
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation for version 2.
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
global $config;
|
||||
|
||||
// Login check.
|
||||
check_login();
|
||||
|
||||
require_once $config['homedir'].'/vendor/autoload.php';
|
||||
// TODO: include file functions.
|
||||
require_once $config['homedir'].'/include/functions_visual_map.php';
|
||||
|
||||
|
||||
/**
|
||||
* Function for return button visual console edition.
|
||||
*
|
||||
* @param string $idDiv Id button.
|
||||
* @param string $label Label and title button.
|
||||
* @param string $class Class button.
|
||||
* @param boolean $disabled Disabled button.
|
||||
*
|
||||
* @return void Retun button.
|
||||
*/
|
||||
function visual_map_print_button_editor_refactor(
|
||||
$idDiv,
|
||||
$label,
|
||||
$class='',
|
||||
$disabled=false
|
||||
) {
|
||||
html_print_button(
|
||||
$label,
|
||||
$idDiv,
|
||||
$disabled,
|
||||
'',
|
||||
// "click_button_toolbox('".$idDiv."');",
|
||||
'class="sub visual_editor_button_toolbox '.$idDiv.' '.$class.'"',
|
||||
false,
|
||||
true
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
ui_require_css_file('visual_maps');
|
||||
ui_require_css_file('register');
|
||||
|
||||
// Query parameters.
|
||||
$visualConsoleId = (int) get_parameter(!is_metaconsole() ? 'id' : 'id_visualmap');
|
||||
|
@ -87,7 +135,7 @@ if ($aclWrite || $aclManage) {
|
|||
$hash = md5($config['dbpass'].$visualConsoleId.$config['id_user']);
|
||||
|
||||
$options['public_link']['text'] = '<a href="'.ui_get_full_url(
|
||||
'operation/visual_console/public_console.php?hash='.$hash.'&id_layout='.$visualConsoleId.'&id_user='.$config['id_user']
|
||||
'operation/visual_console/public_console.php?hash='.$hash.'&id_layout='.$visualConsoleId.'&refr='.$refr.'&id_user='.$config['id_user']
|
||||
).'" target="_blank">'.html_print_image(
|
||||
'images/camera_mc.png',
|
||||
true,
|
||||
|
@ -119,11 +167,6 @@ if ($aclWrite || $aclManage) {
|
|||
true,
|
||||
['title' => __('Wizard')]
|
||||
).'</a>';
|
||||
$options['editor']['text'] = '<a href="'.$baseUrl.'&tab=editor&id_visual_console='.$visualConsoleId.'">'.html_print_image(
|
||||
'images/builder.png',
|
||||
true,
|
||||
['title' => __('Builder')]
|
||||
).'</a>';
|
||||
}
|
||||
|
||||
$options['view']['text'] = '<a href="index.php?sec=network&sec2=operation/visual_console/render_view&id='.$visualConsoleId.'&refr='.$refr.'">'.html_print_image(
|
||||
|
@ -158,13 +201,101 @@ if (!is_metaconsole()) {
|
|||
}
|
||||
|
||||
if ($pure === false) {
|
||||
echo '<div class="visual-console-edit-controls">';
|
||||
echo '<span>'.__('Move and resize mode').'</span>';
|
||||
echo '<span>';
|
||||
echo html_print_checkbox_switch('edit-mode', 1, false, true);
|
||||
echo '</span>';
|
||||
echo '<div id ="edit-vc">';
|
||||
echo '<div id ="edit-controls" class="visual-console-edit-controls" style="visibility:hidden">';
|
||||
echo '<div>';
|
||||
visual_map_print_button_editor_refactor(
|
||||
'STATIC_GRAPH',
|
||||
__('Static Image'),
|
||||
'camera_min link-create-item'
|
||||
);
|
||||
visual_map_print_button_editor_refactor(
|
||||
'PERCENTILE_BAR',
|
||||
__('Percentile Item'),
|
||||
'percentile_item_min link-create-item'
|
||||
);
|
||||
visual_map_print_button_editor_refactor(
|
||||
'MODULE_GRAPH',
|
||||
__('Module Graph'),
|
||||
'graph_min link-create-item'
|
||||
);
|
||||
visual_map_print_button_editor_refactor(
|
||||
'DONUT_GRAPH',
|
||||
__('Serialized pie graph'),
|
||||
'donut_graph_min link-create-item'
|
||||
);
|
||||
visual_map_print_button_editor_refactor(
|
||||
'BARS_GRAPH',
|
||||
__('Bars Graph'),
|
||||
'bars_graph_min link-create-item'
|
||||
);
|
||||
visual_map_print_button_editor_refactor(
|
||||
'AUTO_SLA_GRAPH',
|
||||
__('Event history graph'),
|
||||
'auto_sla_graph_min link-create-item'
|
||||
);
|
||||
visual_map_print_button_editor_refactor(
|
||||
'SIMPLE_VALUE',
|
||||
__('Simple Value'),
|
||||
'binary_min link-create-item'
|
||||
);
|
||||
visual_map_print_button_editor_refactor(
|
||||
'LABEL',
|
||||
__('Label'),
|
||||
'label_min link-create-item'
|
||||
);
|
||||
visual_map_print_button_editor_refactor(
|
||||
'ICON',
|
||||
__('Icon'),
|
||||
'icon_min link-create-item'
|
||||
);
|
||||
visual_map_print_button_editor_refactor(
|
||||
'CLOCK',
|
||||
__('Clock'),
|
||||
'clock_min link-create-item'
|
||||
);
|
||||
visual_map_print_button_editor_refactor(
|
||||
'GROUP_ITEM',
|
||||
__('Group'),
|
||||
'group_item_min link-create-item'
|
||||
);
|
||||
visual_map_print_button_editor_refactor(
|
||||
'BOX_ITEM',
|
||||
__('Box'),
|
||||
'box_item link-create-item'
|
||||
);
|
||||
visual_map_print_button_editor_refactor(
|
||||
'LINE_ITEM',
|
||||
__('Line'),
|
||||
'line_item link-create-item'
|
||||
);
|
||||
visual_map_print_button_editor_refactor(
|
||||
'COLOR_CLOUD',
|
||||
__('Color cloud'),
|
||||
'color_cloud_min link-create-item'
|
||||
);
|
||||
enterprise_include_once('include/functions_visual_map_editor.php');
|
||||
enterprise_hook(
|
||||
'enterprise_visual_map_editor_print_toolbox_refactor'
|
||||
);
|
||||
echo '</div>';
|
||||
echo '<div class="visual-console-copy-delete">';
|
||||
visual_map_print_button_editor_refactor(
|
||||
'button_delete',
|
||||
__('Delete Item'),
|
||||
'delete_item delete_min',
|
||||
true
|
||||
);
|
||||
visual_map_print_button_editor_refactor(
|
||||
'button_copy',
|
||||
__('Copy Item'),
|
||||
'copy_item',
|
||||
true
|
||||
);
|
||||
echo '</div>';
|
||||
echo '</div>';
|
||||
echo html_print_checkbox_switch('edit-mode', 1, false, true);
|
||||
echo '</div>';
|
||||
echo '<br />';
|
||||
}
|
||||
|
||||
echo '<div id="visual-console-container"></div>';
|
||||
|
@ -240,6 +371,7 @@ if (!users_can_manage_group_all('AR')) {
|
|||
}
|
||||
|
||||
$ignored_params['refr'] = '';
|
||||
ui_require_javascript_file('tiny_mce', 'include/javascript/tiny_mce/');
|
||||
ui_require_javascript_file('pandora_visual_console');
|
||||
include_javascript_d3();
|
||||
visual_map_load_client_resources();
|
||||
|
@ -249,7 +381,11 @@ $visualConsoleItems = VisualConsole::getItemsFromDB(
|
|||
$visualConsoleId,
|
||||
$aclUserGroups
|
||||
);
|
||||
ui_require_css_file('modal');
|
||||
ui_require_css_file('form');
|
||||
?>
|
||||
<div id="modalVCItemForm"></div>
|
||||
<div id="modalVCItemFormMsg"></div>
|
||||
|
||||
<script type="text/javascript">
|
||||
var container = document.getElementById("visual-console-container");
|
||||
|
@ -259,6 +395,22 @@ $visualConsoleItems = VisualConsole::getItemsFromDB(
|
|||
var handleUpdate = function (prevProps, newProps) {
|
||||
if (!newProps) return;
|
||||
|
||||
//Remove spinner change VC.
|
||||
document
|
||||
.getElementById("visual-console-container")
|
||||
.classList.remove("is-updating");
|
||||
|
||||
var div = document
|
||||
.getElementById("visual-console-container")
|
||||
.querySelector(".div-visual-console-spinner");
|
||||
|
||||
if (div !== null) {
|
||||
var parent = div.parentElement;
|
||||
if (parent !== null) {
|
||||
parent.removeChild(div);
|
||||
}
|
||||
}
|
||||
|
||||
// Change the background color when the fullscreen mode is enabled.
|
||||
if (prevProps
|
||||
&& prevProps.backgroundColor != newProps.backgroundColor
|
||||
|
@ -266,7 +418,7 @@ $visualConsoleItems = VisualConsole::getItemsFromDB(
|
|||
) {
|
||||
var pureBody = document.querySelector("body.pure");
|
||||
var pureContainer = document.querySelector("div#main_pure");
|
||||
|
||||
|
||||
if (pureBody !== null) {
|
||||
pureBody.style.backgroundColor = newProps.backgroundColor
|
||||
}
|
||||
|
@ -340,9 +492,11 @@ $visualConsoleItems = VisualConsole::getItemsFromDB(
|
|||
if ($(this).prop('checked')) {
|
||||
visualConsoleManager.visualConsole.enableEditMode();
|
||||
visualConsoleManager.changeUpdateInterval(0);
|
||||
$('#edit-controls').css('visibility', '');
|
||||
} else {
|
||||
visualConsoleManager.visualConsole.disableEditMode();
|
||||
visualConsoleManager.changeUpdateInterval(<?php echo ($refr * 1000); ?>); // To ms.
|
||||
$('#edit-controls').css('visibility', 'hidden');
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -362,4 +516,98 @@ $visualConsoleItems = VisualConsole::getItemsFromDB(
|
|||
}
|
||||
}
|
||||
});
|
||||
|
||||
visualConsoleManager.visualConsole.onItemSelectionChanged(function (e) {
|
||||
if (e.selected === true) {
|
||||
$('#button-button_delete').prop('disabled', false);
|
||||
$('#button-button_copy').prop('disabled', false);
|
||||
} else {
|
||||
$('#button-button_delete').prop('disabled', true);
|
||||
$('#button-button_copy').prop('disabled', true);
|
||||
}
|
||||
});
|
||||
|
||||
$('#button-button_delete').click(function (event){
|
||||
confirmDialog({
|
||||
title: "<?php echo __('Delete'); ?>",
|
||||
message: "<?php echo __('Are you sure'); ?>"+"?",
|
||||
onAccept: function() {
|
||||
visualConsoleManager.visualConsole.elements.forEach(item => {
|
||||
if (item.meta.isSelected === true) {
|
||||
visualConsoleManager.deleteItem(item);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
$('#button-button_copy').click(function (event){
|
||||
visualConsoleManager.visualConsole.elements.forEach(item => {
|
||||
if (item.meta.isSelected === true) {
|
||||
visualConsoleManager.copyItem(item);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
$('.link-create-item').click(function (event){
|
||||
var type = event.target.id.substr(7);
|
||||
visualConsoleManager.createItem(type);
|
||||
});
|
||||
|
||||
/**
|
||||
* Process ajax responses and shows a dialog with results.
|
||||
*/
|
||||
function handleFormResponse(data) {
|
||||
var title = "<?php echo __('Success'); ?>";
|
||||
var text = '';
|
||||
var failed = 0;
|
||||
try {
|
||||
data = JSON.parse(data);
|
||||
text = data['result'];
|
||||
} catch (err) {
|
||||
title = "<?php echo __('Failed'); ?>";
|
||||
text = err.message;
|
||||
failed = 1;
|
||||
}
|
||||
if (!failed && data['error'] != undefined) {
|
||||
title = "<?php echo __('Failed'); ?>";
|
||||
text = data['error'];
|
||||
failed = 1;
|
||||
}
|
||||
if (data['report'] != undefined) {
|
||||
data['report'].forEach(function (item){
|
||||
text += '<br>'+item;
|
||||
});
|
||||
}
|
||||
|
||||
if (failed == 1) {
|
||||
$('#modalVCItemFormMsg').empty();
|
||||
$('#modalVCItemFormMsg').html(text);
|
||||
$('#modalVCItemFormMsg').dialog({
|
||||
width: 450,
|
||||
position: {
|
||||
my: 'center',
|
||||
at: 'center',
|
||||
of: window,
|
||||
collision: 'fit'
|
||||
},
|
||||
title: title,
|
||||
buttons: [
|
||||
{
|
||||
class: "ui-widget ui-state-default ui-corner-all ui-button-text-only sub ok submit-next",
|
||||
text: 'OK',
|
||||
click: function(e) {
|
||||
$(this).dialog('close');
|
||||
}
|
||||
}
|
||||
]
|
||||
});
|
||||
// Failed.
|
||||
return false;
|
||||
}
|
||||
|
||||
// Success, return result.
|
||||
return data['result'];
|
||||
}
|
||||
|
||||
</script>
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
declare module "*.png";
|
||||
declare module "*.jpg";
|
||||
declare module "*.gif";
|
||||
declare module "*.svg";
|
||||
declare module "*.eot";
|
||||
declare module "*.ttf";
|
||||
declare module "*.woff";
|
||||
declare module "*.woff2";
|
|
@ -192,6 +192,19 @@
|
|||
"minimist": "^1.2.0"
|
||||
}
|
||||
},
|
||||
"@fortawesome/fontawesome-common-types": {
|
||||
"version": "0.2.20",
|
||||
"resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-0.2.20.tgz",
|
||||
"integrity": "sha512-5wo0pMNS4gWTkplFAPSfNq4poXwLcgj8+khZs9/zbWMxC0hi6qnehXOrX7i7+Y7XyTQForja2WpR7Nz6LY2BtQ=="
|
||||
},
|
||||
"@fortawesome/free-solid-svg-icons": {
|
||||
"version": "5.10.0",
|
||||
"resolved": "https://registry.npmjs.org/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-5.10.0.tgz",
|
||||
"integrity": "sha512-Ndt0GR9wU66lBLGMRZN2jv8LEDx+VTfwmnqYKLQ3VttH4ikgTpqBhdr7UF4M3GFYt1CwftrPVuKOUAFleYg7xA==",
|
||||
"requires": {
|
||||
"@fortawesome/fontawesome-common-types": "^0.2.20"
|
||||
}
|
||||
},
|
||||
"@jest/console": {
|
||||
"version": "24.7.1",
|
||||
"resolved": "https://registry.npmjs.org/@jest/console/-/console-24.7.1.tgz",
|
||||
|
@ -4842,9 +4855,9 @@
|
|||
}
|
||||
},
|
||||
"lodash": {
|
||||
"version": "4.17.11",
|
||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz",
|
||||
"integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg=="
|
||||
"version": "4.17.14",
|
||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.14.tgz",
|
||||
"integrity": "sha512-mmKYbW3GLuJeX+iGP+Y7Gp1AiGHGbXHCOh/jZmrawMmsE7MS4znI3RL2FsjbqOyMayHInjOeykW7PEajUk1/xw=="
|
||||
},
|
||||
"lodash.sortby": {
|
||||
"version": "4.7.0",
|
||||
|
@ -5096,9 +5109,9 @@
|
|||
}
|
||||
},
|
||||
"mixin-deep": {
|
||||
"version": "1.3.1",
|
||||
"resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.1.tgz",
|
||||
"integrity": "sha512-8ZItLHeEgaqEvd5lYBXfm4EZSFCX29Jb9K+lAHhDKzReKBQKj3R+7NOF6tjqYi9t4oI8VUfaWITJQm86wnXGNQ==",
|
||||
"version": "1.3.2",
|
||||
"resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz",
|
||||
"integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==",
|
||||
"requires": {
|
||||
"for-in": "^1.0.2",
|
||||
"is-extendable": "^1.0.1"
|
||||
|
@ -6428,9 +6441,9 @@
|
|||
"integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc="
|
||||
},
|
||||
"set-value": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.0.tgz",
|
||||
"integrity": "sha512-hw0yxk9GT/Hr5yJEYnHNKYXkIA8mVJgd9ditYZCe16ZczcaELYYcfvaXesNACk2O8O0nTiPQcQhGUQj8JLzeeg==",
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz",
|
||||
"integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==",
|
||||
"requires": {
|
||||
"extend-shallow": "^2.0.1",
|
||||
"is-extendable": "^0.1.1",
|
||||
|
@ -7289,35 +7302,14 @@
|
|||
}
|
||||
},
|
||||
"union-value": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.0.tgz",
|
||||
"integrity": "sha1-XHHDTLW61dzr4+oM0IIHulqhrqQ=",
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz",
|
||||
"integrity": "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==",
|
||||
"requires": {
|
||||
"arr-union": "^3.1.0",
|
||||
"get-value": "^2.0.6",
|
||||
"is-extendable": "^0.1.1",
|
||||
"set-value": "^0.4.3"
|
||||
},
|
||||
"dependencies": {
|
||||
"extend-shallow": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
|
||||
"integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
|
||||
"requires": {
|
||||
"is-extendable": "^0.1.0"
|
||||
}
|
||||
},
|
||||
"set-value": {
|
||||
"version": "0.4.3",
|
||||
"resolved": "https://registry.npmjs.org/set-value/-/set-value-0.4.3.tgz",
|
||||
"integrity": "sha1-fbCPnT0i3H945Trzw79GZuzfzPE=",
|
||||
"requires": {
|
||||
"extend-shallow": "^2.0.1",
|
||||
"is-extendable": "^0.1.1",
|
||||
"is-plain-object": "^2.0.1",
|
||||
"to-object-path": "^0.3.0"
|
||||
}
|
||||
}
|
||||
"set-value": "^2.0.1"
|
||||
}
|
||||
},
|
||||
"uniq": {
|
||||
|
@ -7427,9 +7419,9 @@
|
|||
},
|
||||
"dependencies": {
|
||||
"mime": {
|
||||
"version": "2.4.0",
|
||||
"resolved": "https://registry.npmjs.org/mime/-/mime-2.4.0.tgz",
|
||||
"integrity": "sha512-ikBcWwyqXQSHKtciCcctu9YfPbFYZ4+gbHEmE0Q8jzcTYQg5dHCr3g2wwAZjPoJfQVXZq6KXAjpXOTf5/cjT7w=="
|
||||
"version": "2.4.4",
|
||||
"resolved": "https://registry.npmjs.org/mime/-/mime-2.4.4.tgz",
|
||||
"integrity": "sha512-LRxmNwziLPT828z+4YkNzloCFC2YM4wrB99k+AV5ZbEyfGNWfG8SO1FUXLmLDBSo89NrJZ4DIWeLjy1CHGhMGA=="
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
},
|
||||
"homepage": "https://github.com/pandorafms/pandorafms#readme",
|
||||
"dependencies": {
|
||||
"@fortawesome/free-solid-svg-icons": "^5.10.0",
|
||||
"@types/d3-shape": "^1.3.1",
|
||||
"@types/jest": "^24.0.11",
|
||||
"@typescript-eslint/eslint-plugin": "^1.6.0",
|
||||
|
|
|
@ -0,0 +1,254 @@
|
|||
import TypedEvent, { Listener, Disposable } from "./lib/TypedEvent";
|
||||
import { AnyObject, UnknownObject } from "./lib/types";
|
||||
import { t } from "./lib";
|
||||
|
||||
interface InputGroupDataRequestedEvent {
|
||||
identifier: string;
|
||||
params: UnknownObject;
|
||||
done: (error: Error | null, data?: unknown) => void;
|
||||
}
|
||||
|
||||
// TODO: Document
|
||||
export abstract class InputGroup<Data extends {} = {}> {
|
||||
private _name: string = "";
|
||||
private _element?: HTMLElement;
|
||||
public readonly initialData: Data;
|
||||
protected currentData: Partial<Data> = {};
|
||||
// Event manager for data requests.
|
||||
private readonly dataRequestedEventManager = new TypedEvent<
|
||||
InputGroupDataRequestedEvent
|
||||
>();
|
||||
|
||||
public constructor(name: string, initialData: Data) {
|
||||
this.name = name;
|
||||
this.initialData = initialData;
|
||||
}
|
||||
|
||||
public set name(name: string) {
|
||||
if (name.length === 0) throw new RangeError("empty name");
|
||||
this._name = name;
|
||||
}
|
||||
|
||||
public get name(): string {
|
||||
return this._name;
|
||||
}
|
||||
|
||||
public get data(): Partial<Data> {
|
||||
return { ...this.currentData };
|
||||
}
|
||||
|
||||
public get element(): HTMLElement {
|
||||
if (this._element == null) {
|
||||
const element = document.createElement("div");
|
||||
element.className = `input-group input-group-${this.name}`;
|
||||
|
||||
const content = this.createContent();
|
||||
|
||||
if (content instanceof Array) {
|
||||
content.forEach(element.appendChild);
|
||||
} else {
|
||||
element.appendChild(content);
|
||||
}
|
||||
|
||||
this._element = element;
|
||||
}
|
||||
|
||||
return this._element;
|
||||
}
|
||||
|
||||
public reset(): void {
|
||||
this.currentData = {};
|
||||
}
|
||||
|
||||
protected updateData(data: Partial<Data>): void {
|
||||
this.currentData = {
|
||||
...this.currentData,
|
||||
...data
|
||||
};
|
||||
// TODO: Update item.
|
||||
}
|
||||
|
||||
protected requestData(
|
||||
identifier: string,
|
||||
params: UnknownObject,
|
||||
done: (error: Error | null, data?: unknown) => void
|
||||
): void {
|
||||
this.dataRequestedEventManager.emit({ identifier, params, done });
|
||||
}
|
||||
|
||||
public onDataRequested(
|
||||
listener: Listener<InputGroupDataRequestedEvent>
|
||||
): Disposable {
|
||||
return this.dataRequestedEventManager.on(listener);
|
||||
}
|
||||
|
||||
protected abstract createContent(): HTMLElement | HTMLElement[];
|
||||
|
||||
// public abstract get isValid(): boolean;
|
||||
}
|
||||
|
||||
export interface SubmitFormEvent {
|
||||
nativeEvent: Event;
|
||||
data: AnyObject;
|
||||
}
|
||||
|
||||
// TODO: Document
|
||||
export class FormContainer {
|
||||
public readonly title: string;
|
||||
private inputGroupsByName: { [name: string]: InputGroup } = {};
|
||||
private enabledInputGroupNames: string[] = [];
|
||||
// Event manager for submit events.
|
||||
private readonly submitEventManager = new TypedEvent<SubmitFormEvent>();
|
||||
// Event manager for item data requests.
|
||||
private readonly itemDataRequestedEventManager = new TypedEvent<
|
||||
InputGroupDataRequestedEvent
|
||||
>();
|
||||
private handleItemDataRequested = this.itemDataRequestedEventManager.emit;
|
||||
|
||||
public constructor(
|
||||
title: string,
|
||||
inputGroups: InputGroup[] = [],
|
||||
enabledInputGroups: string[] = []
|
||||
) {
|
||||
this.title = title;
|
||||
|
||||
if (inputGroups.length > 0) {
|
||||
this.inputGroupsByName = inputGroups.reduce((prevVal, inputGroup) => {
|
||||
// Add event handlers.
|
||||
inputGroup.onDataRequested(this.handleItemDataRequested);
|
||||
prevVal[inputGroup.name] = inputGroup;
|
||||
return prevVal;
|
||||
}, this.inputGroupsByName);
|
||||
}
|
||||
|
||||
if (enabledInputGroups.length > 0) {
|
||||
this.enabledInputGroupNames = [
|
||||
...this.enabledInputGroupNames,
|
||||
...enabledInputGroups.filter(
|
||||
name => this.inputGroupsByName[name] != null
|
||||
)
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
public getInputGroup(inputGroupName: string): InputGroup | null {
|
||||
return this.inputGroupsByName[inputGroupName] || null;
|
||||
}
|
||||
|
||||
public addInputGroup(
|
||||
inputGroup: InputGroup,
|
||||
index: number | null = null
|
||||
): FormContainer {
|
||||
// Add event handlers.
|
||||
inputGroup.onDataRequested(this.handleItemDataRequested);
|
||||
this.inputGroupsByName[inputGroup.name] = inputGroup;
|
||||
|
||||
// Remove the current stored name if exist.
|
||||
this.enabledInputGroupNames = this.enabledInputGroupNames.filter(
|
||||
name => name !== inputGroup.name
|
||||
);
|
||||
|
||||
if (index !== null) {
|
||||
if (index <= 0) {
|
||||
this.enabledInputGroupNames = [
|
||||
inputGroup.name,
|
||||
...this.enabledInputGroupNames
|
||||
];
|
||||
} else if (index >= this.enabledInputGroupNames.length) {
|
||||
this.enabledInputGroupNames = [
|
||||
...this.enabledInputGroupNames,
|
||||
inputGroup.name
|
||||
];
|
||||
} else {
|
||||
this.enabledInputGroupNames = [
|
||||
// part of the array before the specified index
|
||||
...this.enabledInputGroupNames.slice(0, index),
|
||||
// inserted item
|
||||
inputGroup.name,
|
||||
// part of the array after the specified index
|
||||
...this.enabledInputGroupNames.slice(index)
|
||||
];
|
||||
}
|
||||
} else {
|
||||
this.enabledInputGroupNames = [
|
||||
...this.enabledInputGroupNames,
|
||||
inputGroup.name
|
||||
];
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public removeInputGroup(inputGroupName: string): FormContainer {
|
||||
delete this.inputGroupsByName[inputGroupName];
|
||||
// Remove the current stored name.
|
||||
this.enabledInputGroupNames = this.enabledInputGroupNames.filter(
|
||||
name => name !== inputGroupName
|
||||
);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public getFormElement(
|
||||
type: "creation" | "update" = "update"
|
||||
): HTMLFormElement {
|
||||
const form = document.createElement("form");
|
||||
form.id = "visual-console-item-edition";
|
||||
form.className = "visual-console-item-edition";
|
||||
form.addEventListener("submit", e => {
|
||||
e.preventDefault();
|
||||
this.submitEventManager.emit({
|
||||
nativeEvent: e,
|
||||
data: this.enabledInputGroupNames.reduce((data, name) => {
|
||||
if (this.inputGroupsByName[name]) {
|
||||
data = {
|
||||
...data,
|
||||
...this.inputGroupsByName[name].data
|
||||
};
|
||||
}
|
||||
return data;
|
||||
}, {})
|
||||
});
|
||||
});
|
||||
|
||||
const formContent = document.createElement("div");
|
||||
formContent.className = "input-groups";
|
||||
|
||||
this.enabledInputGroupNames.forEach(name => {
|
||||
if (this.inputGroupsByName[name]) {
|
||||
formContent.appendChild(this.inputGroupsByName[name].element);
|
||||
}
|
||||
});
|
||||
|
||||
form.appendChild(formContent);
|
||||
|
||||
return form;
|
||||
}
|
||||
|
||||
public reset(): void {
|
||||
this.enabledInputGroupNames.forEach(name => {
|
||||
if (this.inputGroupsByName[name]) {
|
||||
this.inputGroupsByName[name].reset();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// public get isValid(): boolean {
|
||||
// for (let i = 0; i < this.enabledInputGroupNames.length; i++) {
|
||||
// const inputGroup = this.inputGroupsByName[this.enabledInputGroupNames[i]];
|
||||
// if (inputGroup && !inputGroup.isValid) return false;
|
||||
// }
|
||||
|
||||
// return true;
|
||||
// }
|
||||
|
||||
public onSubmit(listener: Listener<SubmitFormEvent>): Disposable {
|
||||
return this.submitEventManager.on(listener);
|
||||
}
|
||||
|
||||
public onInputGroupDataRequested(
|
||||
listener: Listener<InputGroupDataRequestedEvent>
|
||||
): Disposable {
|
||||
return this.itemDataRequestedEventManager.on(listener);
|
||||
}
|
||||
}
|
|
@ -3,7 +3,9 @@ import {
|
|||
Size,
|
||||
AnyObject,
|
||||
WithModuleProps,
|
||||
ItemMeta
|
||||
ItemMeta,
|
||||
LinkedVisualConsoleProps,
|
||||
WithAgentProps
|
||||
} from "./lib/types";
|
||||
import {
|
||||
sizePropsDecoder,
|
||||
|
@ -16,9 +18,11 @@ import {
|
|||
humanTime,
|
||||
addMovementListener,
|
||||
debounce,
|
||||
addResizementListener
|
||||
addResizementListener,
|
||||
t
|
||||
} from "./lib";
|
||||
import TypedEvent, { Listener, Disposable } from "./lib/TypedEvent";
|
||||
import { FormContainer, InputGroup } from "./Form";
|
||||
|
||||
// Enum: https://www.typescriptlang.org/docs/handbook/enums.html.
|
||||
export const enum ItemType {
|
||||
|
@ -56,19 +60,18 @@ export interface ItemProps extends Position, Size {
|
|||
isOnTop: boolean;
|
||||
parentId: number | null;
|
||||
aclGroupId: number | null;
|
||||
cacheExpiration: number | null;
|
||||
}
|
||||
|
||||
// FIXME: Fix type compatibility.
|
||||
export interface ItemClickEvent<Props extends ItemProps> {
|
||||
// data: Props;
|
||||
data: AnyObject;
|
||||
export interface ItemClickEvent {
|
||||
item: VisualConsoleItem<ItemProps>;
|
||||
nativeEvent: Event;
|
||||
}
|
||||
|
||||
// FIXME: Fix type compatibility.
|
||||
export interface ItemRemoveEvent<Props extends ItemProps> {
|
||||
export interface ItemRemoveEvent {
|
||||
// data: Props;
|
||||
data: AnyObject;
|
||||
item: VisualConsoleItem<ItemProps>;
|
||||
}
|
||||
|
||||
export interface ItemMovedEvent {
|
||||
|
@ -83,8 +86,12 @@ export interface ItemResizedEvent {
|
|||
newSize: Size;
|
||||
}
|
||||
|
||||
export interface ItemSelectionChangedEvent {
|
||||
selected: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract a valid enum value from a raw label positi9on value.
|
||||
* Extract a valid enum value from a raw label position value.
|
||||
* @param labelPosition Raw value.
|
||||
*/
|
||||
const parseLabelPosition = (
|
||||
|
@ -128,11 +135,87 @@ export function itemBasePropsDecoder(data: AnyObject): ItemProps | never {
|
|||
isOnTop: parseBoolean(data.isOnTop),
|
||||
parentId: parseIntOr(data.parentId, null),
|
||||
aclGroupId: parseIntOr(data.aclGroupId, null),
|
||||
cacheExpiration: parseIntOr(data.cacheExpiration, null),
|
||||
...sizePropsDecoder(data), // Object spread. It will merge the properties of the two objects.
|
||||
...positionPropsDecoder(data) // Object spread. It will merge the properties of the two objects.
|
||||
};
|
||||
}
|
||||
|
||||
//TODO: Document
|
||||
export function titleItem(id: number): string {
|
||||
let title = "";
|
||||
switch (id) {
|
||||
case ItemType.STATIC_GRAPH:
|
||||
title = t("Static image");
|
||||
break;
|
||||
case ItemType.MODULE_GRAPH:
|
||||
title = t("Module graph");
|
||||
break;
|
||||
case ItemType.SIMPLE_VALUE:
|
||||
title = t("Simple value");
|
||||
break;
|
||||
case ItemType.PERCENTILE_BAR:
|
||||
title = t("Percentile item");
|
||||
break;
|
||||
case ItemType.LABEL:
|
||||
title = t("Label");
|
||||
break;
|
||||
case ItemType.ICON:
|
||||
title = t("Icon");
|
||||
break;
|
||||
case ItemType.SIMPLE_VALUE_MAX:
|
||||
title = t("Simple value");
|
||||
break;
|
||||
case ItemType.SIMPLE_VALUE_MIN:
|
||||
title = t("Simple value");
|
||||
break;
|
||||
case ItemType.SIMPLE_VALUE_AVG:
|
||||
title = t("Simple value");
|
||||
break;
|
||||
case ItemType.PERCENTILE_BUBBLE:
|
||||
title = t("Percentile item");
|
||||
break;
|
||||
case ItemType.SERVICE:
|
||||
title = t("Service");
|
||||
break;
|
||||
case ItemType.GROUP_ITEM:
|
||||
title = t("Group");
|
||||
break;
|
||||
case ItemType.BOX_ITEM:
|
||||
title = t("Box");
|
||||
break;
|
||||
case ItemType.LINE_ITEM:
|
||||
title = t("Line");
|
||||
break;
|
||||
case ItemType.AUTO_SLA_GRAPH:
|
||||
title = t("Event history graph");
|
||||
break;
|
||||
case ItemType.CIRCULAR_PROGRESS_BAR:
|
||||
title = t("Percentile item");
|
||||
break;
|
||||
case ItemType.CIRCULAR_INTERIOR_PROGRESS_BAR:
|
||||
title = t("Percentile item");
|
||||
break;
|
||||
case ItemType.DONUT_GRAPH:
|
||||
title = t("Serialized pie graph");
|
||||
break;
|
||||
case ItemType.BARS_GRAPH:
|
||||
title = t("Bars graph");
|
||||
break;
|
||||
case ItemType.CLOCK:
|
||||
title = t("Clock");
|
||||
break;
|
||||
case ItemType.COLOR_CLOUD:
|
||||
title = t("Color cloud");
|
||||
break;
|
||||
default:
|
||||
title = t("Item");
|
||||
break;
|
||||
}
|
||||
|
||||
return title;
|
||||
}
|
||||
|
||||
/**
|
||||
* Base class of the visual console items. Should be extended to use its capabilities.
|
||||
*/
|
||||
|
@ -142,19 +225,31 @@ abstract class VisualConsoleItem<Props extends ItemProps> {
|
|||
// Metadata of the item.
|
||||
private _metadata: ItemMeta;
|
||||
// Reference to the DOM element which will contain the item.
|
||||
public elementRef: HTMLElement;
|
||||
public readonly labelElementRef: HTMLElement;
|
||||
public elementRef: HTMLElement = document.createElement("div");
|
||||
public labelElementRef: HTMLElement = document.createElement("div");
|
||||
// Reference to the DOM element which will contain the view of the item which extends this class.
|
||||
protected readonly childElementRef: HTMLElement;
|
||||
protected childElementRef: HTMLElement = document.createElement("div");
|
||||
// Event manager for click events.
|
||||
private readonly clickEventManager = new TypedEvent<ItemClickEvent<Props>>();
|
||||
private readonly clickEventManager = new TypedEvent<ItemClickEvent>();
|
||||
// Event manager for double click events.
|
||||
private readonly dblClickEventManager = new TypedEvent<ItemClickEvent>();
|
||||
// Event manager for moved events.
|
||||
private readonly movedEventManager = new TypedEvent<ItemMovedEvent>();
|
||||
// Event manager for stopped movement events.
|
||||
private readonly movementFinishedEventManager = new TypedEvent<
|
||||
ItemMovedEvent
|
||||
>();
|
||||
// Event manager for resized events.
|
||||
private readonly resizedEventManager = new TypedEvent<ItemResizedEvent>();
|
||||
// Event manager for resize finished events.
|
||||
private readonly resizeFinishedEventManager = new TypedEvent<
|
||||
ItemResizedEvent
|
||||
>();
|
||||
// Event manager for remove events.
|
||||
private readonly removeEventManager = new TypedEvent<
|
||||
ItemRemoveEvent<Props>
|
||||
private readonly removeEventManager = new TypedEvent<ItemRemoveEvent>();
|
||||
// Event manager for selection change events.
|
||||
private readonly selectionChangedEventManager = new TypedEvent<
|
||||
ItemSelectionChangedEvent
|
||||
>();
|
||||
// List of references to clean the event listeners.
|
||||
private readonly disposables: Disposable[] = [];
|
||||
|
@ -164,6 +259,10 @@ abstract class VisualConsoleItem<Props extends ItemProps> {
|
|||
private debouncedMovementSave = debounce(
|
||||
500, // ms.
|
||||
(x: Position["x"], y: Position["y"]) => {
|
||||
// Update the metadata information.
|
||||
// Don't use the .meta property cause we don't need DOM updates.
|
||||
this._metadata.isBeingMoved = false;
|
||||
|
||||
const prevPosition = {
|
||||
x: this.props.x,
|
||||
y: this.props.y
|
||||
|
@ -178,7 +277,7 @@ abstract class VisualConsoleItem<Props extends ItemProps> {
|
|||
// Save the new position to the props.
|
||||
this.move(x, y);
|
||||
// Emit the movement event.
|
||||
this.movedEventManager.emit({
|
||||
this.movementFinishedEventManager.emit({
|
||||
item: this,
|
||||
prevPosition: prevPosition,
|
||||
newPosition: newPosition
|
||||
|
@ -197,8 +296,30 @@ abstract class VisualConsoleItem<Props extends ItemProps> {
|
|||
this.removeMovement = addMovementListener(
|
||||
element,
|
||||
(x: Position["x"], y: Position["y"]) => {
|
||||
const prevPosition = {
|
||||
x: this.props.x,
|
||||
y: this.props.y
|
||||
};
|
||||
const newPosition = { x, y };
|
||||
|
||||
this.meta = {
|
||||
...this.meta,
|
||||
isSelected: true
|
||||
};
|
||||
|
||||
if (!this.positionChanged(prevPosition, newPosition)) return;
|
||||
|
||||
// Update the metadata information.
|
||||
// Don't use the .meta property cause we don't need DOM updates.
|
||||
this._metadata.isBeingMoved = true;
|
||||
// Move the DOM element.
|
||||
this.moveElement(x, y);
|
||||
// Emit the movement event.
|
||||
this.movedEventManager.emit({
|
||||
item: this,
|
||||
prevPosition: prevPosition,
|
||||
newPosition: newPosition
|
||||
});
|
||||
// Run the save function.
|
||||
this.debouncedMovementSave(x, y);
|
||||
}
|
||||
|
@ -219,21 +340,23 @@ abstract class VisualConsoleItem<Props extends ItemProps> {
|
|||
private debouncedResizementSave = debounce(
|
||||
500, // ms.
|
||||
(width: Size["width"], height: Size["height"]) => {
|
||||
// Update the metadata information.
|
||||
// Don't use the .meta property cause we don't need DOM updates.
|
||||
this._metadata.isBeingResized = false;
|
||||
|
||||
const prevSize = {
|
||||
width: this.props.width,
|
||||
height: this.props.height
|
||||
};
|
||||
const newSize = {
|
||||
width: width,
|
||||
height: height
|
||||
};
|
||||
const newSize = { width, height };
|
||||
|
||||
if (!this.sizeChanged(prevSize, newSize)) return;
|
||||
|
||||
// Save the new position to the props.
|
||||
this.resize(width, height);
|
||||
// Emit the resizement event.
|
||||
this.resizedEventManager.emit({
|
||||
|
||||
// Emit the resize finished event.
|
||||
this.resizeFinishedEventManager.emit({
|
||||
item: this,
|
||||
prevSize: prevSize,
|
||||
newSize: newSize
|
||||
|
@ -252,6 +375,10 @@ abstract class VisualConsoleItem<Props extends ItemProps> {
|
|||
this.removeResizement = addResizementListener(
|
||||
element,
|
||||
(width: Size["width"], height: Size["height"]) => {
|
||||
// Update the metadata information.
|
||||
// Don't use the .meta property cause we don't need DOM updates.
|
||||
this._metadata.isBeingResized = true;
|
||||
|
||||
// The label it's outside the item's size, so we need
|
||||
// to get rid of its size to get the real size of the
|
||||
// item's content.
|
||||
|
@ -273,8 +400,22 @@ abstract class VisualConsoleItem<Props extends ItemProps> {
|
|||
}
|
||||
}
|
||||
|
||||
const prevSize = {
|
||||
width: this.props.width,
|
||||
height: this.props.height
|
||||
};
|
||||
const newSize = { width, height };
|
||||
|
||||
if (!this.sizeChanged(prevSize, newSize)) return;
|
||||
|
||||
// Move the DOM element.
|
||||
this.resizeElement(width, height);
|
||||
// Emit the resizement event.
|
||||
this.resizedEventManager.emit({
|
||||
item: this,
|
||||
prevSize,
|
||||
newSize
|
||||
});
|
||||
// Run the save function.
|
||||
this.debouncedResizementSave(width, height);
|
||||
}
|
||||
|
@ -296,10 +437,21 @@ abstract class VisualConsoleItem<Props extends ItemProps> {
|
|||
*/
|
||||
protected abstract createDomElement(): HTMLElement;
|
||||
|
||||
public constructor(props: Props, metadata: ItemMeta) {
|
||||
public constructor(
|
||||
props: Props,
|
||||
metadata: ItemMeta,
|
||||
deferInit: boolean = false
|
||||
) {
|
||||
this.itemProps = props;
|
||||
this._metadata = metadata;
|
||||
|
||||
if (!deferInit) this.init();
|
||||
}
|
||||
|
||||
/**
|
||||
* To create and append the DOM elements.
|
||||
*/
|
||||
protected init(): void {
|
||||
/*
|
||||
* Get a HTMLElement which represents the container box
|
||||
* of the Visual Console item. This element will manage
|
||||
|
@ -317,12 +469,13 @@ abstract class VisualConsoleItem<Props extends ItemProps> {
|
|||
this.childElementRef = this.createDomElement();
|
||||
|
||||
// Insert the elements into the container.
|
||||
this.elementRef.append(this.childElementRef, this.labelElementRef);
|
||||
this.elementRef.appendChild(this.childElementRef);
|
||||
this.elementRef.appendChild(this.labelElementRef);
|
||||
|
||||
// Resize element.
|
||||
this.resizeElement(props.width, props.height);
|
||||
this.resizeElement(this.itemProps.width, this.itemProps.height);
|
||||
// Set label position.
|
||||
this.changeLabelPosition(props.labelPosition);
|
||||
this.changeLabelPosition(this.itemProps.labelPosition);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -339,26 +492,57 @@ abstract class VisualConsoleItem<Props extends ItemProps> {
|
|||
}
|
||||
|
||||
box.className = "visual-console-item";
|
||||
box.style.zIndex = this.props.isOnTop ? "2" : "1";
|
||||
if (this.props.isOnTop) {
|
||||
box.classList.add("is-on-top");
|
||||
}
|
||||
box.style.left = `${this.props.x}px`;
|
||||
box.style.top = `${this.props.y}px`;
|
||||
// Init the click listener.
|
||||
|
||||
// Init the click listeners.
|
||||
box.addEventListener("dblclick", e => {
|
||||
if (!this.meta.isBeingMoved && !this.meta.isBeingResized) {
|
||||
this.unSelectItem();
|
||||
this.selectItem();
|
||||
|
||||
this.dblClickEventManager.emit({
|
||||
item: this,
|
||||
nativeEvent: e
|
||||
});
|
||||
}
|
||||
});
|
||||
box.addEventListener("click", e => {
|
||||
if (this.meta.editMode) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
} else {
|
||||
this.clickEventManager.emit({ data: this.props, nativeEvent: e });
|
||||
// Add loading click item.
|
||||
if (this.itemProps.isLinkEnabled) {
|
||||
const divParent = document.createElement("div");
|
||||
divParent.className = "div-visual-console-spinner";
|
||||
const divSpinner = document.createElement("div");
|
||||
divSpinner.className = "visual-console-spinner";
|
||||
divParent.appendChild(divSpinner);
|
||||
const containerVC = document.getElementById(
|
||||
"visual-console-container"
|
||||
);
|
||||
if (containerVC != null) {
|
||||
containerVC.classList.add("is-updating");
|
||||
containerVC.appendChild(divParent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!this.meta.isBeingMoved && !this.meta.isBeingResized) {
|
||||
this.clickEventManager.emit({
|
||||
item: this,
|
||||
nativeEvent: e
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// Metadata state.
|
||||
if (this.meta.editMode) {
|
||||
box.classList.add("is-editing");
|
||||
// Init the movement listener.
|
||||
this.initMovementListener(box);
|
||||
// Init the resizement listener.
|
||||
this.initResizementListener(box);
|
||||
}
|
||||
if (this.meta.isFetching) {
|
||||
box.classList.add("is-fetching");
|
||||
|
@ -366,6 +550,9 @@ abstract class VisualConsoleItem<Props extends ItemProps> {
|
|||
if (this.meta.isUpdating) {
|
||||
box.classList.add("is-updating");
|
||||
}
|
||||
if (this.meta.isSelected) {
|
||||
box.classList.add("is-selected");
|
||||
}
|
||||
|
||||
return box;
|
||||
}
|
||||
|
@ -388,8 +575,10 @@ abstract class VisualConsoleItem<Props extends ItemProps> {
|
|||
const cell = document.createElement("td");
|
||||
|
||||
cell.innerHTML = label;
|
||||
row.append(cell);
|
||||
table.append(emptyRow1, row, emptyRow2);
|
||||
row.appendChild(cell);
|
||||
table.appendChild(emptyRow1);
|
||||
table.appendChild(row);
|
||||
table.appendChild(emptyRow2);
|
||||
table.style.textAlign = "center";
|
||||
|
||||
// Change the table size depending on its position.
|
||||
|
@ -411,7 +600,7 @@ abstract class VisualConsoleItem<Props extends ItemProps> {
|
|||
}
|
||||
|
||||
// element.innerHTML = this.props.label;
|
||||
element.append(table);
|
||||
element.appendChild(table);
|
||||
}
|
||||
|
||||
return element;
|
||||
|
@ -482,6 +671,15 @@ abstract class VisualConsoleItem<Props extends ItemProps> {
|
|||
* @param newProps
|
||||
*/
|
||||
public set props(newProps: Props) {
|
||||
this.setProps(newProps);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clasic and protected version of the setter of the `props` property.
|
||||
* Useful to override it from children classes.
|
||||
* @param newProps
|
||||
*/
|
||||
protected setProps(newProps: Props) {
|
||||
const prevProps = this.props;
|
||||
// Update the internal props.
|
||||
this.itemProps = newProps;
|
||||
|
@ -512,14 +710,26 @@ abstract class VisualConsoleItem<Props extends ItemProps> {
|
|||
}
|
||||
|
||||
/**
|
||||
* Clasic and protected version of the setter of the `meta` property.
|
||||
* Classic version of the setter of the `meta` property.
|
||||
* Useful to override it from children classes.
|
||||
* @param newProps
|
||||
*/
|
||||
protected setMeta(newMetadata: ItemMeta) {
|
||||
public setMeta(newMetadata: Partial<ItemMeta>): void {
|
||||
const prevMetadata = this._metadata;
|
||||
// Update the internal meta.
|
||||
this._metadata = newMetadata;
|
||||
this._metadata = {
|
||||
...prevMetadata,
|
||||
...newMetadata
|
||||
};
|
||||
|
||||
if (
|
||||
typeof newMetadata.isSelected !== "undefined" &&
|
||||
prevMetadata.isSelected !== newMetadata.isSelected
|
||||
) {
|
||||
this.selectionChangedEventManager.emit({
|
||||
selected: newMetadata.isSelected
|
||||
});
|
||||
}
|
||||
|
||||
// From this point, things which rely on this.props can access to the changes.
|
||||
|
||||
|
@ -572,12 +782,16 @@ abstract class VisualConsoleItem<Props extends ItemProps> {
|
|||
if (!prevProps || prevProps.labelPosition !== this.props.labelPosition) {
|
||||
this.changeLabelPosition(this.props.labelPosition);
|
||||
}
|
||||
//Change z-index class is-on-top
|
||||
if (!prevProps || prevProps.isOnTop !== this.props.isOnTop) {
|
||||
if (this.props.isOnTop) {
|
||||
this.elementRef.classList.add("is-on-top");
|
||||
} else {
|
||||
this.elementRef.classList.remove("is-on-top");
|
||||
}
|
||||
}
|
||||
// Change link.
|
||||
if (
|
||||
prevProps &&
|
||||
(prevProps.isLinkEnabled !== this.props.isLinkEnabled ||
|
||||
(this.props.isLinkEnabled && prevProps.link !== this.props.link))
|
||||
) {
|
||||
if (prevProps && prevProps.isLinkEnabled !== this.props.isLinkEnabled) {
|
||||
const container = this.createContainerDomElement();
|
||||
// Add the children of the old element.
|
||||
container.innerHTML = this.elementRef.innerHTML;
|
||||
|
@ -585,7 +799,12 @@ abstract class VisualConsoleItem<Props extends ItemProps> {
|
|||
const attrs = this.elementRef.attributes;
|
||||
for (let i = 0; i < attrs.length; i++) {
|
||||
if (attrs[i].nodeName !== "id") {
|
||||
container.setAttributeNode(attrs[i]);
|
||||
let cloneIsNeeded = this.elementRef.getAttributeNode(
|
||||
attrs[i].nodeName
|
||||
);
|
||||
if (cloneIsNeeded !== null) {
|
||||
container.setAttributeNode(<any>cloneIsNeeded.cloneNode());
|
||||
}
|
||||
}
|
||||
}
|
||||
// Replace the reference.
|
||||
|
@ -597,16 +816,21 @@ abstract class VisualConsoleItem<Props extends ItemProps> {
|
|||
this.elementRef = container;
|
||||
}
|
||||
|
||||
if (
|
||||
prevProps &&
|
||||
(this.props.isLinkEnabled && prevProps.link !== this.props.link)
|
||||
) {
|
||||
if (this.props.link !== null) {
|
||||
this.elementRef.setAttribute("href", this.props.link);
|
||||
}
|
||||
}
|
||||
|
||||
// Change metadata related things.
|
||||
if (!prevMeta || prevMeta.editMode !== this.meta.editMode) {
|
||||
if (this.meta.editMode) {
|
||||
this.elementRef.classList.add("is-editing");
|
||||
this.initMovementListener(this.elementRef);
|
||||
this.initResizementListener(this.elementRef);
|
||||
} else {
|
||||
this.elementRef.classList.remove("is-editing");
|
||||
this.stopMovementListener();
|
||||
this.stopResizementListener();
|
||||
}
|
||||
}
|
||||
if (!prevMeta || prevMeta.isFetching !== this.meta.isFetching) {
|
||||
|
@ -616,11 +840,36 @@ abstract class VisualConsoleItem<Props extends ItemProps> {
|
|||
this.elementRef.classList.remove("is-fetching");
|
||||
}
|
||||
}
|
||||
|
||||
if (!prevMeta || prevMeta.isUpdating !== this.meta.isUpdating) {
|
||||
if (this.meta.isUpdating) {
|
||||
this.elementRef.classList.add("is-updating");
|
||||
|
||||
const divParent = document.createElement("div");
|
||||
divParent.className = "div-visual-console-spinner";
|
||||
const divSpinner = document.createElement("div");
|
||||
divSpinner.className = "visual-console-spinner";
|
||||
divParent.appendChild(divSpinner);
|
||||
this.elementRef.appendChild(divParent);
|
||||
} else {
|
||||
this.elementRef.classList.remove("is-updating");
|
||||
|
||||
const div = this.elementRef.querySelector(
|
||||
".div-visual-console-spinner"
|
||||
);
|
||||
if (div !== null) {
|
||||
const parent = div.parentElement;
|
||||
if (parent !== null) {
|
||||
parent.removeChild(div);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!prevMeta || prevMeta.isSelected !== this.meta.isSelected) {
|
||||
if (this.meta.isSelected) {
|
||||
this.elementRef.classList.add("is-selected");
|
||||
} else {
|
||||
this.elementRef.classList.remove("is-selected");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -630,7 +879,7 @@ abstract class VisualConsoleItem<Props extends ItemProps> {
|
|||
*/
|
||||
public remove(): void {
|
||||
// Call the remove event.
|
||||
this.removeEventManager.emit({ data: this.props });
|
||||
this.removeEventManager.emit({ item: this });
|
||||
// Event listeners.
|
||||
this.disposables.forEach(disposable => {
|
||||
try {
|
||||
|
@ -785,7 +1034,7 @@ abstract class VisualConsoleItem<Props extends ItemProps> {
|
|||
* To add an event handler to the click of the linked visual console elements.
|
||||
* @param listener Function which is going to be executed when a linked console is clicked.
|
||||
*/
|
||||
public onClick(listener: Listener<ItemClickEvent<Props>>): Disposable {
|
||||
public onClick(listener: Listener<ItemClickEvent>): Disposable {
|
||||
/*
|
||||
* The '.on' function returns a function which will clean the event
|
||||
* listener when executed. We store all the 'dispose' functions to
|
||||
|
@ -797,6 +1046,22 @@ abstract class VisualConsoleItem<Props extends ItemProps> {
|
|||
return disposable;
|
||||
}
|
||||
|
||||
/**
|
||||
* To add an event handler to the double click of the linked visual console elements.
|
||||
* @param listener Function which is going to be executed when a linked console is double clicked.
|
||||
*/
|
||||
public onDblClick(listener: Listener<ItemClickEvent>): Disposable {
|
||||
/*
|
||||
* The '.on' function returns a function which will clean the event
|
||||
* listener when executed. We store all the 'dispose' functions to
|
||||
* call them when the item should be cleared.
|
||||
*/
|
||||
const disposable = this.dblClickEventManager.on(listener);
|
||||
this.disposables.push(disposable);
|
||||
|
||||
return disposable;
|
||||
}
|
||||
|
||||
/**
|
||||
* To add an event handler to the movement of visual console elements.
|
||||
* @param listener Function which is going to be executed when a linked console is moved.
|
||||
|
@ -813,6 +1078,22 @@ abstract class VisualConsoleItem<Props extends ItemProps> {
|
|||
return disposable;
|
||||
}
|
||||
|
||||
/**
|
||||
* To add an event handler to the movement stopped of visual console elements.
|
||||
* @param listener Function which is going to be executed when a linked console's movement is finished.
|
||||
*/
|
||||
public onMovementFinished(listener: Listener<ItemMovedEvent>): Disposable {
|
||||
/*
|
||||
* The '.on' function returns a function which will clean the event
|
||||
* listener when executed. We store all the 'dispose' functions to
|
||||
* call them when the item should be cleared.
|
||||
*/
|
||||
const disposable = this.movementFinishedEventManager.on(listener);
|
||||
this.disposables.push(disposable);
|
||||
|
||||
return disposable;
|
||||
}
|
||||
|
||||
/**
|
||||
* To add an event handler to the resizement of visual console elements.
|
||||
* @param listener Function which is going to be executed when a linked console is moved.
|
||||
|
@ -829,11 +1110,27 @@ abstract class VisualConsoleItem<Props extends ItemProps> {
|
|||
return disposable;
|
||||
}
|
||||
|
||||
/**
|
||||
* To add an event handler to the resizement finish of visual console elements.
|
||||
* @param listener Function which is going to be executed when a linked console is finished resizing.
|
||||
*/
|
||||
public onResizeFinished(listener: Listener<ItemResizedEvent>): Disposable {
|
||||
/*
|
||||
* The '.on' function returns a function which will clean the event
|
||||
* listener when executed. We store all the 'dispose' functions to
|
||||
* call them when the item should be cleared.
|
||||
*/
|
||||
const disposable = this.resizeFinishedEventManager.on(listener);
|
||||
this.disposables.push(disposable);
|
||||
|
||||
return disposable;
|
||||
}
|
||||
|
||||
/**
|
||||
* To add an event handler to the removal of the item.
|
||||
* @param listener Function which is going to be executed when a item is removed.
|
||||
*/
|
||||
public onRemove(listener: Listener<ItemRemoveEvent<Props>>): Disposable {
|
||||
public onRemove(listener: Listener<ItemRemoveEvent>): Disposable {
|
||||
/*
|
||||
* The '.on' function returns a function which will clean the event
|
||||
* listener when executed. We store all the 'dispose' functions to
|
||||
|
@ -844,6 +1141,68 @@ abstract class VisualConsoleItem<Props extends ItemProps> {
|
|||
|
||||
return disposable;
|
||||
}
|
||||
|
||||
/**
|
||||
* To add an event handler to item selection.
|
||||
* @param listener Function which is going to be executed when a item is removed.
|
||||
*/
|
||||
public onSelectionChanged(
|
||||
listener: Listener<ItemSelectionChangedEvent>
|
||||
): Disposable {
|
||||
/*
|
||||
* The '.on' function returns a function which will clean the event
|
||||
* listener when executed. We store all the 'dispose' functions to
|
||||
* call them when the item should be cleared.
|
||||
*/
|
||||
const disposable = this.selectionChangedEventManager.on(listener);
|
||||
this.disposables.push(disposable);
|
||||
|
||||
return disposable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Select an item.
|
||||
* @param itemId Item Id.
|
||||
* @param unique To remove the selection of other items or not.
|
||||
*/
|
||||
public selectItem(): void {
|
||||
this.meta = {
|
||||
...this.meta,
|
||||
isSelected: true
|
||||
};
|
||||
|
||||
this.initMovementListener(this.elementRef);
|
||||
if (this.props.type !== 13) {
|
||||
this.initResizementListener(this.elementRef);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Unselect an item.
|
||||
* @param itemId Item Id.
|
||||
*/
|
||||
public unSelectItem(): void {
|
||||
this.meta = {
|
||||
...this.meta,
|
||||
isSelected: false
|
||||
};
|
||||
|
||||
this.stopMovementListener();
|
||||
if (this.props.type !== 13) {
|
||||
this.stopResizementListener();
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Document
|
||||
public getFormContainer(): FormContainer {
|
||||
return VisualConsoleItem.getFormContainer(this.props);
|
||||
}
|
||||
|
||||
// TODO: Document
|
||||
public static getFormContainer(props: Partial<ItemProps>): FormContainer {
|
||||
const title: string = props.type ? titleItem(props.type) : t("Item");
|
||||
return new FormContainer(title, [], []);
|
||||
}
|
||||
}
|
||||
|
||||
export default VisualConsoleItem;
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
import { AnyObject, Size } from "./lib/types";
|
||||
import { AnyObject, Size, Position, WithModuleProps } from "./lib/types";
|
||||
import {
|
||||
parseBoolean,
|
||||
sizePropsDecoder,
|
||||
parseIntOr,
|
||||
notEmptyStringOr,
|
||||
itemMetaDecoder
|
||||
itemMetaDecoder,
|
||||
t,
|
||||
ellipsize
|
||||
} from "./lib";
|
||||
import Item, {
|
||||
ItemType,
|
||||
|
@ -12,7 +14,8 @@ import Item, {
|
|||
ItemClickEvent,
|
||||
ItemRemoveEvent,
|
||||
ItemMovedEvent,
|
||||
ItemResizedEvent
|
||||
ItemResizedEvent,
|
||||
ItemSelectionChangedEvent
|
||||
} from "./Item";
|
||||
import StaticGraph, { staticGraphPropsDecoder } from "./items/StaticGraph";
|
||||
import Icon, { iconPropsDecoder } from "./items/Icon";
|
||||
|
@ -20,7 +23,7 @@ import ColorCloud, { colorCloudPropsDecoder } from "./items/ColorCloud";
|
|||
import Group, { groupPropsDecoder } from "./items/Group";
|
||||
import Clock, { clockPropsDecoder } from "./items/Clock";
|
||||
import Box, { boxPropsDecoder } from "./items/Box";
|
||||
import Line, { linePropsDecoder } from "./items/Line";
|
||||
import Line, { linePropsDecoder, LineMovedEvent } from "./items/Line";
|
||||
import Label, { labelPropsDecoder } from "./items/Label";
|
||||
import SimpleValue, { simpleValuePropsDecoder } from "./items/SimpleValue";
|
||||
import EventsHistory, {
|
||||
|
@ -32,6 +35,7 @@ import DonutGraph, { donutGraphPropsDecoder } from "./items/DonutGraph";
|
|||
import BarsGraph, { barsGraphPropsDecoder } from "./items/BarsGraph";
|
||||
import ModuleGraph, { moduleGraphPropsDecoder } from "./items/ModuleGraph";
|
||||
import Service, { servicePropsDecoder } from "./items/Service";
|
||||
import { FormContainer } from "./Form";
|
||||
|
||||
// TODO: Document.
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-function-return-type
|
||||
|
@ -203,13 +207,19 @@ export default class VisualConsole {
|
|||
[key: string]: Line;
|
||||
} = {};
|
||||
// Event manager for click events.
|
||||
private readonly clickEventManager = new TypedEvent<
|
||||
ItemClickEvent<ItemProps>
|
||||
>();
|
||||
private readonly clickEventManager = new TypedEvent<ItemClickEvent>();
|
||||
// Event manager for double click events.
|
||||
private readonly dblClickEventManager = new TypedEvent<ItemClickEvent>();
|
||||
// Event manager for move events.
|
||||
private readonly movedEventManager = new TypedEvent<ItemMovedEvent>();
|
||||
// Event manager for line move events.
|
||||
private readonly lineMovedEventManager = new TypedEvent<LineMovedEvent>();
|
||||
// Event manager for resize events.
|
||||
private readonly resizedEventManager = new TypedEvent<ItemResizedEvent>();
|
||||
// Event manager for remove events.
|
||||
private readonly selectionChangedEventManager = new TypedEvent<
|
||||
ItemSelectionChangedEvent
|
||||
>();
|
||||
// List of references to clean the event listeners.
|
||||
private readonly disposables: Disposable[] = [];
|
||||
|
||||
|
@ -217,38 +227,150 @@ export default class VisualConsole {
|
|||
* React to a click on an element.
|
||||
* @param e Event object.
|
||||
*/
|
||||
private handleElementClick: (e: ItemClickEvent<ItemProps>) => void = e => {
|
||||
private handleElementClick: (e: ItemClickEvent) => void = e => {
|
||||
this.clickEventManager.emit(e);
|
||||
// console.log(`Clicked element #${e.data.id}`, e);
|
||||
};
|
||||
|
||||
/**
|
||||
* React to a double click on an element.
|
||||
* @param e Event object.
|
||||
*/
|
||||
private handleElementDblClick: (e: ItemClickEvent) => void = e => {
|
||||
this.dblClickEventManager.emit(e);
|
||||
// console.log(`Double clicked element #${e.data.id}`, e);
|
||||
};
|
||||
|
||||
/**
|
||||
* React to a movement on an element.
|
||||
* @param e Event object.
|
||||
*/
|
||||
private handleElementMovement: (e: ItemMovedEvent) => void = e => {
|
||||
this.movedEventManager.emit(e);
|
||||
// Move their relation lines.
|
||||
const itemId = e.item.props.id;
|
||||
const relations = this.getItemRelations(itemId);
|
||||
|
||||
relations.forEach(relation => {
|
||||
if (relation.parentId === itemId) {
|
||||
// Move the line start.
|
||||
relation.line.props = {
|
||||
...relation.line.props,
|
||||
startPosition: this.getVisualCenter(e.newPosition, e.item)
|
||||
};
|
||||
} else if (relation.childId === itemId) {
|
||||
// Move the line end.
|
||||
relation.line.props = {
|
||||
...relation.line.props,
|
||||
endPosition: this.getVisualCenter(e.newPosition, e.item)
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
// console.log(`Moved element #${e.item.props.id}`, e);
|
||||
};
|
||||
|
||||
/**
|
||||
* React to a movement finished on an element.
|
||||
* @param e Event object.
|
||||
*/
|
||||
private handleElementMovementFinished: (e: ItemMovedEvent) => void = e => {
|
||||
this.movedEventManager.emit(e);
|
||||
// console.log(`Movement finished for element #${e.item.props.id}`, e);
|
||||
};
|
||||
|
||||
/**
|
||||
* React to a line movement.
|
||||
* @param e Event object.
|
||||
*/
|
||||
private handleLineElementMovementFinished: (
|
||||
e: LineMovedEvent
|
||||
) => void = e => {
|
||||
this.lineMovedEventManager.emit(e);
|
||||
// console.log(`Movement finished for element #${e.item.props.id}`, e);
|
||||
};
|
||||
|
||||
/**
|
||||
* React to a resizement on an element.
|
||||
* @param e Event object.
|
||||
*/
|
||||
private handleElementResizement: (e: ItemResizedEvent) => void = e => {
|
||||
this.resizedEventManager.emit(e);
|
||||
// Move their relation lines.
|
||||
const item = e.item;
|
||||
const props = item.props;
|
||||
const itemId = props.id;
|
||||
const relations = this.getItemRelations(itemId);
|
||||
|
||||
const position = {
|
||||
x: props.x,
|
||||
y: props.y
|
||||
};
|
||||
|
||||
const meta = this.elementsById[itemId].meta;
|
||||
|
||||
this.elementsById[itemId].meta = {
|
||||
...meta,
|
||||
isUpdating: true
|
||||
};
|
||||
|
||||
relations.forEach(relation => {
|
||||
if (relation.parentId === itemId) {
|
||||
// Move the line start.
|
||||
relation.line.props = {
|
||||
...relation.line.props,
|
||||
startPosition: this.getVisualCenter(position, item)
|
||||
};
|
||||
} else if (relation.childId === itemId) {
|
||||
// Move the line end.
|
||||
relation.line.props = {
|
||||
...relation.line.props,
|
||||
endPosition: this.getVisualCenter(position, item)
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
// console.log(`Resized element #${e.item.props.id}`, e);
|
||||
};
|
||||
|
||||
/**
|
||||
* React to a finished resizement on an element.
|
||||
* @param e Event object.
|
||||
*/
|
||||
private handleElementResizementFinished: (
|
||||
e: ItemResizedEvent
|
||||
) => void = e => {
|
||||
this.resizedEventManager.emit(e);
|
||||
// console.log(`Resize fonished for element #${e.item.props.id}`, e);
|
||||
};
|
||||
|
||||
/**
|
||||
* Clear some element references.
|
||||
* @param e Event object.
|
||||
*/
|
||||
private handleElementRemove: (e: ItemRemoveEvent<ItemProps>) => void = e => {
|
||||
private handleElementRemove: (e: ItemRemoveEvent) => void = e => {
|
||||
// Remove the element from the list and its relations.
|
||||
this.elementIds = this.elementIds.filter(id => id !== e.data.id);
|
||||
delete this.elementsById[e.data.id];
|
||||
this.clearRelations(e.data.id);
|
||||
this.elementIds = this.elementIds.filter(id => id !== e.item.props.id);
|
||||
delete this.elementsById[e.item.props.id];
|
||||
this.clearRelations(e.item.props.id);
|
||||
};
|
||||
|
||||
/**
|
||||
* React to element selection change
|
||||
* @param e Event object.
|
||||
*/
|
||||
private handleElementSelectionChanged: (
|
||||
e: ItemSelectionChangedEvent
|
||||
) => void = e => {
|
||||
if (this.elements.filter(item => item.meta.isSelected == true).length > 0) {
|
||||
e.selected = true;
|
||||
} else {
|
||||
e.selected = false;
|
||||
}
|
||||
this.selectionChangedEventManager.emit(e);
|
||||
};
|
||||
|
||||
// TODO: Document
|
||||
private handleContainerClick: (e: MouseEvent) => void = () => {
|
||||
this.unSelectItems();
|
||||
};
|
||||
|
||||
public constructor(
|
||||
|
@ -262,44 +384,20 @@ export default class VisualConsole {
|
|||
// Force the first render.
|
||||
this.render();
|
||||
|
||||
// Sort by isOnTop, id ASC
|
||||
// Sort by id ASC
|
||||
items = items.sort(function(a, b) {
|
||||
if (
|
||||
a.isOnTop == null ||
|
||||
b.isOnTop == null ||
|
||||
a.id == null ||
|
||||
b.id == null
|
||||
) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (a.isOnTop && !b.isOnTop) return 1;
|
||||
else if (!a.isOnTop && b.isOnTop) return -1;
|
||||
if (a.id == null || b.id == null) return 0;
|
||||
else if (a.id > b.id) return 1;
|
||||
else return -1;
|
||||
});
|
||||
|
||||
// Initialize the items.
|
||||
items.forEach(item => {
|
||||
try {
|
||||
const itemInstance = itemInstanceFrom(item);
|
||||
// Add the item to the list.
|
||||
this.elementsById[itemInstance.props.id] = itemInstance;
|
||||
this.elementIds.push(itemInstance.props.id);
|
||||
// Item event handlers.
|
||||
itemInstance.onClick(this.handleElementClick);
|
||||
itemInstance.onMoved(this.handleElementMovement);
|
||||
itemInstance.onResized(this.handleElementResizement);
|
||||
itemInstance.onRemove(this.handleElementRemove);
|
||||
// Add the item to the DOM.
|
||||
this.containerRef.append(itemInstance.elementRef);
|
||||
} catch (error) {
|
||||
console.log("Error creating a new element:", error.message);
|
||||
}
|
||||
});
|
||||
items.forEach(item => this.addElement(item, this));
|
||||
|
||||
// Create lines.
|
||||
this.buildRelations();
|
||||
|
||||
this.containerRef.addEventListener("click", this.handleContainerClick);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -313,6 +411,43 @@ export default class VisualConsole {
|
|||
.filter(_ => _ != null) as Item<ItemProps>[];
|
||||
}
|
||||
|
||||
/**
|
||||
* To create a new element add it to the DOM.
|
||||
* @param item. Raw representation of the item's data.
|
||||
*/
|
||||
public addElement(item: AnyObject, context: this = this) {
|
||||
try {
|
||||
const itemInstance = itemInstanceFrom(item);
|
||||
// Add the item to the list.
|
||||
context.elementsById[itemInstance.props.id] = itemInstance;
|
||||
context.elementIds.push(itemInstance.props.id);
|
||||
// Item event handlers.
|
||||
itemInstance.onRemove(context.handleElementRemove);
|
||||
itemInstance.onSelectionChanged(context.handleElementSelectionChanged);
|
||||
|
||||
// TODO:Continue
|
||||
itemInstance.onClick(context.handleElementClick);
|
||||
itemInstance.onDblClick(context.handleElementDblClick);
|
||||
itemInstance.onMoved(context.handleElementMovement);
|
||||
itemInstance.onMovementFinished(context.handleElementMovementFinished);
|
||||
if (itemInstance instanceof Line) {
|
||||
itemInstance.onLineMovementFinished(
|
||||
context.handleLineElementMovementFinished
|
||||
);
|
||||
} else {
|
||||
itemInstance.onResized(context.handleElementResizement);
|
||||
itemInstance.onResizeFinished(context.handleElementResizementFinished);
|
||||
}
|
||||
|
||||
// Add the item to the DOM.
|
||||
context.containerRef.append(itemInstance.elementRef);
|
||||
return itemInstance;
|
||||
} catch (error) {
|
||||
console.log("Error creating a new element:", error.message);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Public setter of the `elements` property.
|
||||
* @param items.
|
||||
|
@ -339,18 +474,7 @@ export default class VisualConsole {
|
|||
if (item.id) {
|
||||
if (this.elementsById[item.id] == null) {
|
||||
// New item.
|
||||
try {
|
||||
const itemInstance = itemInstanceFrom(item);
|
||||
// Add the item to the list.
|
||||
this.elementsById[itemInstance.props.id] = itemInstance;
|
||||
// Item event handlers.
|
||||
itemInstance.onClick(this.handleElementClick);
|
||||
itemInstance.onRemove(this.handleElementRemove);
|
||||
// Add the item to the DOM.
|
||||
this.containerRef.append(itemInstance.elementRef);
|
||||
} catch (error) {
|
||||
console.log("Error creating a new element:", error.message);
|
||||
}
|
||||
this.addElement(item);
|
||||
} else {
|
||||
// Update item.
|
||||
try {
|
||||
|
@ -366,6 +490,22 @@ export default class VisualConsole {
|
|||
this.buildRelations();
|
||||
}
|
||||
|
||||
/**
|
||||
* Public setter of the `element` property.
|
||||
* @param item.
|
||||
*/
|
||||
public updateElement(item: AnyObject): void {
|
||||
// Update item.
|
||||
try {
|
||||
this.elementsById[item.id].props = decodeProps(item);
|
||||
} catch (error) {
|
||||
console.log("Error updating element:", error.message);
|
||||
}
|
||||
|
||||
// Re-build relations.
|
||||
this.buildRelations();
|
||||
}
|
||||
|
||||
/**
|
||||
* Public accessor of the `props` property.
|
||||
* @return Properties.
|
||||
|
@ -466,6 +606,8 @@ export default class VisualConsole {
|
|||
this.elementIds = [];
|
||||
// Clear relations.
|
||||
this.clearRelations();
|
||||
// Remove the click event listener.
|
||||
this.containerRef.removeEventListener("click", this.handleContainerClick);
|
||||
// Clean container.
|
||||
this.containerRef.innerHTML = "";
|
||||
}
|
||||
|
@ -473,7 +615,7 @@ export default class VisualConsole {
|
|||
/**
|
||||
* Create line elements which connect the elements with their parents.
|
||||
*/
|
||||
private buildRelations(): void {
|
||||
public buildRelations(): void {
|
||||
// Clear relations.
|
||||
this.clearRelations();
|
||||
// Add relations.
|
||||
|
@ -521,6 +663,84 @@ export default class VisualConsole {
|
|||
return this.relations[identifier] || null;
|
||||
}
|
||||
|
||||
// TODO: Document.
|
||||
private getItemRelations(
|
||||
itemId: number
|
||||
): {
|
||||
parentId: number;
|
||||
childId: number;
|
||||
line: Line;
|
||||
}[] {
|
||||
const itemRelations = [];
|
||||
|
||||
for (let key in this.relations) {
|
||||
const ids = key.split("|");
|
||||
const parentId = Number.parseInt(ids[0]);
|
||||
const childId = Number.parseInt(ids[1]);
|
||||
|
||||
if (itemId === parentId || itemId === childId) {
|
||||
itemRelations.push({
|
||||
parentId,
|
||||
childId,
|
||||
line: this.relations[key]
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return itemRelations;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the visual center of the item. It's ussually the center of the
|
||||
* content, like the label doesn't exist.
|
||||
* @param position Initial position.
|
||||
* @param element Element we want to use.
|
||||
*/
|
||||
private getVisualCenter(
|
||||
position: Position,
|
||||
element: Item<ItemProps>
|
||||
): Position {
|
||||
let x = position.x + element.elementRef.clientWidth / 2;
|
||||
let y = position.y + element.elementRef.clientHeight / 2;
|
||||
if (
|
||||
typeof element.props.label !== "undefined" ||
|
||||
element.props.label !== "" ||
|
||||
element.props.label !== null
|
||||
) {
|
||||
switch (element.props.labelPosition) {
|
||||
case "up":
|
||||
y =
|
||||
position.y +
|
||||
(element.elementRef.clientHeight +
|
||||
element.labelElementRef.clientHeight) /
|
||||
2;
|
||||
break;
|
||||
case "down":
|
||||
y =
|
||||
position.y +
|
||||
(element.elementRef.clientHeight -
|
||||
element.labelElementRef.clientHeight) /
|
||||
2;
|
||||
break;
|
||||
case "right":
|
||||
x =
|
||||
position.x +
|
||||
(element.elementRef.clientWidth -
|
||||
element.labelElementRef.clientWidth) /
|
||||
2;
|
||||
break;
|
||||
case "left":
|
||||
x =
|
||||
position.x +
|
||||
(element.elementRef.clientWidth +
|
||||
element.labelElementRef.clientWidth) /
|
||||
2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return { x, y };
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a new line item to represent a relation between the items.
|
||||
* @param parent Parent item.
|
||||
|
@ -537,15 +757,8 @@ export default class VisualConsole {
|
|||
}
|
||||
|
||||
// Get the items center.
|
||||
const startX = parent.props.x + parent.elementRef.clientWidth / 2;
|
||||
const startY =
|
||||
parent.props.y +
|
||||
(parent.elementRef.clientHeight - parent.labelElementRef.clientHeight) /
|
||||
2;
|
||||
const endX = child.props.x + child.elementRef.clientWidth / 2;
|
||||
const endY =
|
||||
child.props.y +
|
||||
(child.elementRef.clientHeight - child.labelElementRef.clientHeight) / 2;
|
||||
const { x: startX, y: startY } = this.getVisualCenter(parent.props, parent);
|
||||
const { x: endX, y: endY } = this.getVisualCenter(child.props, child);
|
||||
|
||||
const line = new Line(
|
||||
linePropsDecoder({
|
||||
|
@ -578,9 +791,7 @@ export default class VisualConsole {
|
|||
* Add an event handler to the click of the linked visual console elements.
|
||||
* @param listener Function which is going to be executed when a linked console is clicked.
|
||||
*/
|
||||
public onItemClick(
|
||||
listener: Listener<ItemClickEvent<ItemProps>>
|
||||
): Disposable {
|
||||
public onItemClick(listener: Listener<ItemClickEvent>): Disposable {
|
||||
/*
|
||||
* The '.on' function returns a function which will clean the event
|
||||
* listener when executed. We store all the 'dispose' functions to
|
||||
|
@ -592,6 +803,22 @@ export default class VisualConsole {
|
|||
return disposable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an event handler to the double click of the linked visual console elements.
|
||||
* @param listener Function which is going to be executed when a linked console is double clicked.
|
||||
*/
|
||||
public onItemDblClick(listener: Listener<ItemClickEvent>): Disposable {
|
||||
/*
|
||||
* The '.on' function returns a function which will clean the event
|
||||
* listener when executed. We store all the 'dispose' functions to
|
||||
* call them when the item should be cleared.
|
||||
*/
|
||||
const disposable = this.dblClickEventManager.on(listener);
|
||||
this.disposables.push(disposable);
|
||||
|
||||
return disposable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an event handler to the movement of the visual console elements.
|
||||
* @param listener Function which is going to be executed when a linked console is moved.
|
||||
|
@ -608,6 +835,22 @@ export default class VisualConsole {
|
|||
return disposable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an event handler to the movement of the visual console line elements.
|
||||
* @param listener Function which is going to be executed when a linked console is moved.
|
||||
*/
|
||||
public onLineMoved(listener: Listener<LineMovedEvent>): Disposable {
|
||||
/*
|
||||
* The '.on' function returns a function which will clean the event
|
||||
* listener when executed. We store all the 'dispose' functions to
|
||||
* call them when the item should be cleared.
|
||||
*/
|
||||
const disposable = this.lineMovedEventManager.on(listener);
|
||||
this.disposables.push(disposable);
|
||||
|
||||
return disposable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an event handler to the resizement of the visual console elements.
|
||||
* @param listener Function which is going to be executed when a linked console is moved.
|
||||
|
@ -624,6 +867,24 @@ export default class VisualConsole {
|
|||
return disposable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an event handler to the elements selection change of the visual console .
|
||||
* @param listener Function which is going to be executed when a linked console is moved.
|
||||
*/
|
||||
public onItemSelectionChanged(
|
||||
listener: Listener<ItemSelectionChangedEvent>
|
||||
): Disposable {
|
||||
/*
|
||||
* The '.on' function returns a function which will clean the event
|
||||
* listener when executed. We store all the 'dispose' functions to
|
||||
* call them when the item should be cleared.
|
||||
*/
|
||||
const disposable = this.selectionChangedEventManager.on(listener);
|
||||
this.disposables.push(disposable);
|
||||
|
||||
return disposable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable the edition mode.
|
||||
*/
|
||||
|
@ -643,4 +904,146 @@ export default class VisualConsole {
|
|||
});
|
||||
this.containerRef.classList.remove("is-editing");
|
||||
}
|
||||
|
||||
/**
|
||||
* Select an item.
|
||||
* @param itemId Item Id.
|
||||
* @param unique To remove the selection of other items or not.
|
||||
*/
|
||||
public selectItem(itemId: number, unique: boolean = false): void {
|
||||
if (unique) {
|
||||
this.elementIds.forEach(currentItemId => {
|
||||
const meta = this.elementsById[currentItemId].meta;
|
||||
|
||||
if (currentItemId !== itemId && meta.isSelected) {
|
||||
this.elementsById[currentItemId].unSelectItem();
|
||||
} else if (currentItemId === itemId && !meta.isSelected) {
|
||||
this.elementsById[currentItemId].selectItem();
|
||||
}
|
||||
});
|
||||
} else if (this.elementsById[itemId]) {
|
||||
this.elementsById[itemId].selectItem();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Unselect an item.
|
||||
* @param itemId Item Id.
|
||||
*/
|
||||
public unSelectItem(itemId: number): void {
|
||||
if (this.elementsById[itemId]) {
|
||||
const meta = this.elementsById[itemId].meta;
|
||||
|
||||
if (meta.isSelected) {
|
||||
this.elementsById[itemId].unSelectItem();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Unselect all items.
|
||||
*/
|
||||
public unSelectItems(): void {
|
||||
this.elementIds.forEach(itemId => {
|
||||
if (this.elementsById[itemId]) {
|
||||
this.elementsById[itemId].unSelectItem();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// TODO: Document.
|
||||
public static items = {
|
||||
[ItemType.STATIC_GRAPH]: StaticGraph,
|
||||
[ItemType.MODULE_GRAPH]: ModuleGraph,
|
||||
[ItemType.SIMPLE_VALUE]: SimpleValue,
|
||||
[ItemType.SIMPLE_VALUE_MAX]: SimpleValue,
|
||||
[ItemType.SIMPLE_VALUE_MIN]: SimpleValue,
|
||||
[ItemType.SIMPLE_VALUE_AVG]: SimpleValue,
|
||||
[ItemType.PERCENTILE_BAR]: Percentile,
|
||||
[ItemType.PERCENTILE_BUBBLE]: Percentile,
|
||||
[ItemType.CIRCULAR_PROGRESS_BAR]: Percentile,
|
||||
[ItemType.CIRCULAR_INTERIOR_PROGRESS_BAR]: Percentile,
|
||||
[ItemType.LABEL]: Label,
|
||||
[ItemType.ICON]: Icon,
|
||||
[ItemType.SERVICE]: Service,
|
||||
[ItemType.GROUP_ITEM]: Group,
|
||||
[ItemType.BOX_ITEM]: Box,
|
||||
[ItemType.LINE_ITEM]: Line,
|
||||
[ItemType.AUTO_SLA_GRAPH]: EventsHistory,
|
||||
[ItemType.DONUT_GRAPH]: DonutGraph,
|
||||
[ItemType.BARS_GRAPH]: BarsGraph,
|
||||
[ItemType.CLOCK]: Clock,
|
||||
[ItemType.COLOR_CLOUD]: ColorCloud
|
||||
};
|
||||
|
||||
/**
|
||||
* Relying type item and srcimg and agent and module
|
||||
* name convert name item representative.
|
||||
*
|
||||
* @param item Instance item from extract name.
|
||||
*
|
||||
* @return Name item.
|
||||
*/
|
||||
public static itemDescriptiveName(item: Item<ItemProps>): string {
|
||||
let text: string;
|
||||
switch (item.props.type) {
|
||||
case ItemType.STATIC_GRAPH:
|
||||
text = `${t("Static graph")} - ${(item as StaticGraph).props.imageSrc}`;
|
||||
break;
|
||||
case ItemType.MODULE_GRAPH:
|
||||
text = t("Module graph");
|
||||
break;
|
||||
case ItemType.CLOCK:
|
||||
text = t("Clock");
|
||||
break;
|
||||
case ItemType.BARS_GRAPH:
|
||||
text = t("Bars graph");
|
||||
break;
|
||||
case ItemType.AUTO_SLA_GRAPH:
|
||||
text = t("Event history graph");
|
||||
break;
|
||||
case ItemType.PERCENTILE_BAR:
|
||||
text = t("Percentile bar");
|
||||
break;
|
||||
case ItemType.CIRCULAR_PROGRESS_BAR:
|
||||
text = t("Circular progress bar");
|
||||
break;
|
||||
case ItemType.CIRCULAR_INTERIOR_PROGRESS_BAR:
|
||||
text = t("Circular progress bar (interior)");
|
||||
break;
|
||||
case ItemType.SIMPLE_VALUE:
|
||||
text = t("Simple Value");
|
||||
break;
|
||||
case ItemType.LABEL:
|
||||
text = t("Label");
|
||||
break;
|
||||
case ItemType.GROUP_ITEM:
|
||||
text = t("Group");
|
||||
break;
|
||||
case ItemType.COLOR_CLOUD:
|
||||
text = t("Color cloud");
|
||||
break;
|
||||
case ItemType.ICON:
|
||||
text = `${t("Icon")} - ${(item as Icon).props.imageSrc}`;
|
||||
break;
|
||||
default:
|
||||
text = t("Item");
|
||||
break;
|
||||
}
|
||||
|
||||
const linkedAgentAndModuleProps = item.props as Partial<WithModuleProps>;
|
||||
if (
|
||||
linkedAgentAndModuleProps.agentAlias != null &&
|
||||
linkedAgentAndModuleProps.moduleName != null
|
||||
) {
|
||||
text += ` (${ellipsize(
|
||||
linkedAgentAndModuleProps.agentAlias,
|
||||
18
|
||||
)} - ${ellipsize(linkedAgentAndModuleProps.moduleName, 25)})`;
|
||||
} else if (linkedAgentAndModuleProps.agentAlias != null) {
|
||||
text += ` (${ellipsize(linkedAgentAndModuleProps.agentAlias, 25)})`;
|
||||
}
|
||||
|
||||
return text;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,12 +7,17 @@
|
|||
|
||||
import "./main.css"; // CSS import.
|
||||
import VisualConsole from "./VisualConsole";
|
||||
import * as Form from "./Form";
|
||||
import AsyncTaskManager from "./lib/AsyncTaskManager";
|
||||
|
||||
// Export the VisualConsole class to the global object.
|
||||
// eslint-disable-next-line
|
||||
(window as any).VisualConsole = VisualConsole;
|
||||
|
||||
// Export the VisualConsole's Form classes to the global object.
|
||||
// eslint-disable-next-line
|
||||
(window as any).VisualConsole.Form = Form;
|
||||
|
||||
// Export the AsyncTaskManager class to the global object.
|
||||
// eslint-disable-next-line
|
||||
(window as any).AsyncTaskManager = AsyncTaskManager;
|
||||
|
|
|
@ -1,13 +1,47 @@
|
|||
import { AnyObject, WithModuleProps } from "../lib/types";
|
||||
import { modulePropsDecoder, decodeBase64, stringIsEmpty } from "../lib";
|
||||
import { modulePropsDecoder, decodeBase64, stringIsEmpty, t } from "../lib";
|
||||
import Item, { ItemType, ItemProps, itemBasePropsDecoder } from "../Item";
|
||||
|
||||
export type BarsGraphProps = {
|
||||
type: ItemType.BARS_GRAPH;
|
||||
html: string;
|
||||
backgroundColor: "white" | "black" | "transparent";
|
||||
typeGraph: "horizontal" | "vertical";
|
||||
gridColor: string;
|
||||
} & ItemProps &
|
||||
WithModuleProps;
|
||||
|
||||
/**
|
||||
* Extract a valid enum value from a raw unknown value.
|
||||
* @param BarsGraphProps Raw value.
|
||||
*/
|
||||
const parseBarsGraphProps = (
|
||||
backgroundColor: unknown
|
||||
): BarsGraphProps["backgroundColor"] => {
|
||||
switch (backgroundColor) {
|
||||
case "white":
|
||||
case "black":
|
||||
case "transparent":
|
||||
return backgroundColor;
|
||||
default:
|
||||
return "transparent";
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Extract a valid enum value from a raw unknown value.
|
||||
* @param typeGraph Raw value.
|
||||
*/
|
||||
const parseTypeGraph = (typeGraph: unknown): BarsGraphProps["typeGraph"] => {
|
||||
switch (typeGraph) {
|
||||
case "horizontal":
|
||||
case "vertical":
|
||||
return typeGraph;
|
||||
default:
|
||||
return "vertical";
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Build a valid typed object from a raw object.
|
||||
* This will allow us to ensure the type safety.
|
||||
|
@ -28,6 +62,9 @@ export function barsGraphPropsDecoder(data: AnyObject): BarsGraphProps | never {
|
|||
html: !stringIsEmpty(data.html)
|
||||
? data.html
|
||||
: decodeBase64(data.encodedHtml),
|
||||
backgroundColor: parseBarsGraphProps(data.backgroundColor),
|
||||
typeGraph: parseTypeGraph(data.typeGraph),
|
||||
gridColor: stringIsEmpty(data.gridColor) ? "#000000" : data.gridColor,
|
||||
...modulePropsDecoder(data) // Object spread. It will merge the properties of the two objects.
|
||||
};
|
||||
}
|
||||
|
@ -36,30 +73,20 @@ export default class BarsGraph extends Item<BarsGraphProps> {
|
|||
protected createDomElement(): HTMLElement {
|
||||
const element = document.createElement("div");
|
||||
element.className = "bars-graph";
|
||||
element.innerHTML = this.props.html;
|
||||
|
||||
// Hack to execute the JS after the HTML is added to the DOM.
|
||||
const scripts = element.getElementsByTagName("script");
|
||||
for (let i = 0; i < scripts.length; i++) {
|
||||
setTimeout(() => {
|
||||
if (scripts[i].src.length === 0) eval(scripts[i].innerHTML.trim());
|
||||
}, 0);
|
||||
}
|
||||
element.style.backgroundImage = `url(${this.props.html})`;
|
||||
element.style.backgroundRepeat = "no-repeat";
|
||||
element.style.backgroundSize = `${this.props.width}px ${
|
||||
this.props.height
|
||||
}px`;
|
||||
|
||||
return element;
|
||||
}
|
||||
|
||||
protected updateDomElement(element: HTMLElement): void {
|
||||
element.innerHTML = this.props.html;
|
||||
|
||||
// Hack to execute the JS after the HTML is added to the DOM.
|
||||
const aux = document.createElement("div");
|
||||
aux.innerHTML = this.props.html;
|
||||
const scripts = aux.getElementsByTagName("script");
|
||||
for (let i = 0; i < scripts.length; i++) {
|
||||
if (scripts[i].src.length === 0) {
|
||||
eval(scripts[i].innerHTML.trim());
|
||||
}
|
||||
}
|
||||
element.style.backgroundImage = `url(${this.props.html})`;
|
||||
element.style.backgroundRepeat = "no-repeat";
|
||||
element.style.backgroundSize = `${this.props.width}px ${
|
||||
this.props.height
|
||||
}px`;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { AnyObject } from "../lib/types";
|
||||
import { parseIntOr, notEmptyStringOr } from "../lib";
|
||||
import { parseIntOr, notEmptyStringOr, t } from "../lib";
|
||||
import Item, { ItemType, ItemProps, itemBasePropsDecoder } from "../Item";
|
||||
|
||||
interface BoxProps extends ItemProps {
|
||||
|
@ -13,6 +13,7 @@ interface BoxProps extends ItemProps {
|
|||
borderWidth: number;
|
||||
borderColor: string | null;
|
||||
fillColor: string | null;
|
||||
fillTransparent: boolean | null;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -35,7 +36,8 @@ export function boxPropsDecoder(data: AnyObject): BoxProps | never {
|
|||
// Custom properties.
|
||||
borderWidth: parseIntOr(data.borderWidth, 0),
|
||||
borderColor: notEmptyStringOr(data.borderColor, null),
|
||||
fillColor: notEmptyStringOr(data.fillColor, null)
|
||||
fillColor: notEmptyStringOr(data.fillColor, null),
|
||||
fillTransparent: data.fillTransparent
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -46,8 +48,12 @@ export default class Box extends Item<BoxProps> {
|
|||
// To prevent this item to expand beyond its parent.
|
||||
box.style.boxSizing = "border-box";
|
||||
|
||||
if (this.props.fillColor) {
|
||||
box.style.backgroundColor = this.props.fillColor;
|
||||
if (this.props.fillTransparent) {
|
||||
box.style.backgroundColor = "transparent";
|
||||
} else {
|
||||
if (this.props.fillColor) {
|
||||
box.style.backgroundColor = this.props.fillColor;
|
||||
}
|
||||
}
|
||||
|
||||
// Border.
|
||||
|
@ -65,4 +71,31 @@ export default class Box extends Item<BoxProps> {
|
|||
|
||||
return box;
|
||||
}
|
||||
|
||||
/**
|
||||
* To update the content element.
|
||||
* @override Item.updateDomElement
|
||||
*/
|
||||
protected updateDomElement(element: HTMLElement): void {
|
||||
if (this.props.fillTransparent) {
|
||||
element.style.backgroundColor = "transparent";
|
||||
} else {
|
||||
if (this.props.fillColor) {
|
||||
element.style.backgroundColor = this.props.fillColor;
|
||||
}
|
||||
}
|
||||
|
||||
// Border.
|
||||
if (this.props.borderWidth > 0) {
|
||||
element.style.borderStyle = "solid";
|
||||
// Control the max width to prevent this item to expand beyond its parent.
|
||||
const maxBorderWidth = Math.min(this.props.width, this.props.height) / 2;
|
||||
const borderWidth = Math.min(this.props.borderWidth, maxBorderWidth);
|
||||
element.style.borderWidth = `${borderWidth}px`;
|
||||
|
||||
if (this.props.borderColor) {
|
||||
element.style.borderColor = this.props.borderColor;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,7 +13,8 @@ import {
|
|||
prefixedCssRules,
|
||||
notEmptyStringOr,
|
||||
humanDate,
|
||||
humanTime
|
||||
humanTime,
|
||||
t
|
||||
} from "../../lib";
|
||||
import Item, { ItemProps, itemBasePropsDecoder, ItemType } from "../../Item";
|
||||
|
||||
|
@ -154,6 +155,31 @@ export default class Clock extends Item<ClockProps> {
|
|||
return this.createClock();
|
||||
}
|
||||
|
||||
/**
|
||||
* To update the content element.
|
||||
* @override Item.updateDomElement
|
||||
*/
|
||||
protected updateDomElement(element: HTMLElement): void {
|
||||
// Destructuring assigment: http://es6-features.org/#ObjectMatchingShorthandNotation
|
||||
const { width: newWidth, height: newHeight } = this.getElementSize(
|
||||
this.props.width,
|
||||
this.props.height
|
||||
);
|
||||
|
||||
if (this.props.clockType === "digital") {
|
||||
if (this.meta.isBeingResized === false) {
|
||||
super.resizeElement(this.props.width, this.props.height);
|
||||
}
|
||||
element.classList.replace("analogic-clock", "digital-clock");
|
||||
} else {
|
||||
if (this.meta.isBeingResized === false) {
|
||||
super.resizeElement(newWidth, newHeight);
|
||||
}
|
||||
element.classList.replace("digital-clock", "analogic-clock");
|
||||
}
|
||||
element.innerHTML = this.createDomElement().innerHTML;
|
||||
}
|
||||
|
||||
/**
|
||||
* To remove the event listeners and the elements from the DOM.
|
||||
* @override
|
||||
|
@ -172,15 +198,19 @@ export default class Clock extends Item<ClockProps> {
|
|||
* @param height
|
||||
*/
|
||||
protected resizeElement(width: number, height: number): void {
|
||||
// Destructuring assigment: http://es6-features.org/#ObjectMatchingShorthandNotation
|
||||
const { width: newWidth, height: newHeight } = this.getElementSize(
|
||||
width,
|
||||
height
|
||||
); // Destructuring assigment: http://es6-features.org/#ObjectMatchingShorthandNotation
|
||||
super.resizeElement(newWidth, newHeight);
|
||||
);
|
||||
|
||||
// Re-render the item to force it calculate a new font size.
|
||||
if (this.props.clockType === "digital") {
|
||||
super.resizeElement(width, height);
|
||||
// Replace the old element with the updated date.
|
||||
this.childElementRef.innerHTML = this.createClock().innerHTML;
|
||||
//this.childElementRef.innerHTML = this.createClock().innerHTML;
|
||||
} else {
|
||||
super.resizeElement(newWidth, newHeight);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -586,9 +616,14 @@ export default class Clock extends Item<ClockProps> {
|
|||
diameter = height;
|
||||
}
|
||||
|
||||
let extraHeigth = 0;
|
||||
if (this.props.clockFormat === "datetime") {
|
||||
extraHeigth = height / 8;
|
||||
}
|
||||
|
||||
return {
|
||||
width: diameter,
|
||||
height: diameter
|
||||
height: diameter + extraHeigth
|
||||
};
|
||||
}
|
||||
case "digital": {
|
||||
|
|
|
@ -15,9 +15,6 @@
|
|||
}
|
||||
|
||||
.visual-console-item .digital-clock > span {
|
||||
font-family: "Alarm Clock", "Courier New", Courier, monospace;
|
||||
font-size: 50px;
|
||||
|
||||
/* To improve legibility */
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
|
@ -25,6 +22,11 @@
|
|||
text-shadow: rgba(0, 0, 0, 0.01) 0 0 1px;
|
||||
}
|
||||
|
||||
.visual-console-item .digital-clock > span.time {
|
||||
font-family: "Alarm Clock", "Courier New", Courier, monospace;
|
||||
font-size: 50px;
|
||||
}
|
||||
|
||||
.visual-console-item .digital-clock > span.date {
|
||||
font-size: 25px;
|
||||
}
|
||||
|
|
|
@ -1,16 +1,27 @@
|
|||
import {
|
||||
WithModuleProps,
|
||||
LinkedVisualConsoleProps,
|
||||
AnyObject
|
||||
AnyObject,
|
||||
WithAgentProps
|
||||
} from "../lib/types";
|
||||
import { modulePropsDecoder, linkedVCPropsDecoder } from "../lib";
|
||||
import { modulePropsDecoder, linkedVCPropsDecoder, t } from "../lib";
|
||||
import Item, { itemBasePropsDecoder, ItemType, ItemProps } from "../Item";
|
||||
import { FormContainer, InputGroup } from "../Form";
|
||||
import fontAwesomeIcon from "../lib/FontAwesomeIcon";
|
||||
import { faTrashAlt, faPlusCircle } from "@fortawesome/free-solid-svg-icons";
|
||||
|
||||
export type ColorCloudProps = {
|
||||
type: ItemType.COLOR_CLOUD;
|
||||
color: string;
|
||||
defaultColor: string;
|
||||
colorRanges: {
|
||||
color: string;
|
||||
fromValue: number;
|
||||
toValue: number;
|
||||
}[];
|
||||
// TODO: Add the rest of the color cloud values?
|
||||
} & ItemProps &
|
||||
WithAgentProps &
|
||||
WithModuleProps &
|
||||
LinkedVisualConsoleProps;
|
||||
|
||||
|
@ -35,11 +46,311 @@ export function colorCloudPropsDecoder(
|
|||
...itemBasePropsDecoder(data), // Object spread. It will merge the properties of the two objects.
|
||||
type: ItemType.COLOR_CLOUD,
|
||||
color: data.color,
|
||||
defaultColor: data.defaultColor,
|
||||
colorRanges: data.colorRanges,
|
||||
...modulePropsDecoder(data), // Object spread. It will merge the properties of the two objects.
|
||||
...linkedVCPropsDecoder(data) // Object spread. It will merge the properties of the two objects.
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Class to add item to the Color cloud item form
|
||||
* This item consists of a label and a color type input color.
|
||||
* Element default color is stored in the color property
|
||||
*/
|
||||
class ColorInputGroup extends InputGroup<Partial<ColorCloudProps>> {
|
||||
protected createContent(): HTMLElement | HTMLElement[] {
|
||||
const generalDiv = document.createElement("div");
|
||||
generalDiv.className = "div-input-group";
|
||||
|
||||
const colorLabel = document.createElement("label");
|
||||
colorLabel.textContent = t("Default color");
|
||||
|
||||
generalDiv.appendChild(colorLabel);
|
||||
|
||||
const ColorInput = document.createElement("input");
|
||||
ColorInput.type = "color";
|
||||
ColorInput.required = true;
|
||||
|
||||
ColorInput.value = `${this.currentData.defaultColor ||
|
||||
this.initialData.defaultColor ||
|
||||
"#000000"}`;
|
||||
|
||||
ColorInput.addEventListener("change", e => {
|
||||
this.updateData({
|
||||
defaultColor: (e.target as HTMLInputElement).value
|
||||
});
|
||||
});
|
||||
|
||||
generalDiv.appendChild(ColorInput);
|
||||
|
||||
return generalDiv;
|
||||
}
|
||||
}
|
||||
|
||||
type ColorRanges = ColorCloudProps["colorRanges"];
|
||||
type ColorRange = ColorRanges[0];
|
||||
|
||||
class RangesInputGroup extends InputGroup<Partial<ColorCloudProps>> {
|
||||
protected createContent(): HTMLElement | HTMLElement[] {
|
||||
const generalDiv = document.createElement("div");
|
||||
generalDiv.className = "div-input-group div-ranges-input-group";
|
||||
|
||||
const rangesLabel = this.createLabel("Ranges");
|
||||
|
||||
generalDiv.appendChild(rangesLabel);
|
||||
|
||||
const rangesControlsContainer = document.createElement("div");
|
||||
const createdRangesContainer = document.createElement("div");
|
||||
|
||||
generalDiv.appendChild(createdRangesContainer);
|
||||
generalDiv.appendChild(rangesControlsContainer);
|
||||
|
||||
const colorRanges =
|
||||
this.currentData.colorRanges || this.initialData.colorRanges || [];
|
||||
|
||||
let buildRanges: (ranges: ColorRanges) => void;
|
||||
|
||||
const handleRangeUpdatePartial = (index: number) => (
|
||||
range: ColorRange
|
||||
): void => {
|
||||
const colorRanges =
|
||||
this.currentData.colorRanges || this.initialData.colorRanges || [];
|
||||
this.updateData({
|
||||
colorRanges: [
|
||||
...colorRanges.slice(0, index),
|
||||
range,
|
||||
...colorRanges.slice(index + 1)
|
||||
]
|
||||
});
|
||||
};
|
||||
|
||||
const handleDelete = (index: number) => () => {
|
||||
const colorRanges =
|
||||
this.currentData.colorRanges || this.initialData.colorRanges || [];
|
||||
const newRanges = [
|
||||
...colorRanges.slice(0, index),
|
||||
...colorRanges.slice(index + 1)
|
||||
];
|
||||
|
||||
this.updateData({ colorRanges: newRanges });
|
||||
buildRanges(newRanges);
|
||||
};
|
||||
|
||||
const handleCreate = (range: ColorRange): void => {
|
||||
const colorRanges =
|
||||
this.currentData.colorRanges || this.initialData.colorRanges || [];
|
||||
const newRanges = [...colorRanges, range];
|
||||
this.updateData({ colorRanges: newRanges });
|
||||
buildRanges(newRanges);
|
||||
};
|
||||
|
||||
buildRanges = ranges => {
|
||||
createdRangesContainer.innerHTML = "";
|
||||
ranges.forEach((colorRange, index) =>
|
||||
createdRangesContainer.appendChild(
|
||||
this.rangeContainer(
|
||||
colorRange,
|
||||
handleRangeUpdatePartial(index),
|
||||
handleDelete(index)
|
||||
)
|
||||
)
|
||||
);
|
||||
};
|
||||
|
||||
buildRanges(colorRanges);
|
||||
|
||||
rangesControlsContainer.appendChild(
|
||||
this.initialRangeContainer(handleCreate)
|
||||
);
|
||||
|
||||
return generalDiv;
|
||||
}
|
||||
|
||||
private initialRangeContainer(onCreate: (range: ColorRange) => void) {
|
||||
// TODO: Document
|
||||
const initialState = { color: "#ffffff" };
|
||||
|
||||
let state: Partial<ColorRange> = { ...initialState };
|
||||
|
||||
const handleFromValue = (value: ColorRange["fromValue"]): void => {
|
||||
state.fromValue = value;
|
||||
};
|
||||
const handleToValue = (value: ColorRange["toValue"]): void => {
|
||||
state.toValue = value;
|
||||
};
|
||||
const handleColor = (value: ColorRange["color"]): void => {
|
||||
state.color = value;
|
||||
};
|
||||
|
||||
// User defined type guard.
|
||||
// Docs: https://www.typescriptlang.org/docs/handbook/advanced-types.html#user-defined-type-guards
|
||||
const isValid = (range: Partial<ColorRange>): range is ColorRange =>
|
||||
typeof range.color !== "undefined" &&
|
||||
typeof range.toValue !== "undefined" &&
|
||||
typeof range.fromValue !== "undefined";
|
||||
|
||||
const rangesContainer = document.createElement("div");
|
||||
|
||||
// Div From value.
|
||||
const rangesContainerFromValue = document.createElement("div");
|
||||
const rangesLabelFromValue = this.createLabel("From Value");
|
||||
const rangesInputFromValue = this.createInputNumber(null, handleFromValue);
|
||||
rangesContainerFromValue.appendChild(rangesLabelFromValue);
|
||||
rangesContainerFromValue.appendChild(rangesInputFromValue);
|
||||
rangesContainer.appendChild(rangesContainerFromValue);
|
||||
|
||||
// Div To Value.
|
||||
const rangesDivContainerToValue = document.createElement("div");
|
||||
const rangesLabelToValue = this.createLabel("To Value");
|
||||
const rangesInputToValue = this.createInputNumber(null, handleToValue);
|
||||
rangesContainerFromValue.appendChild(rangesLabelToValue);
|
||||
rangesContainerFromValue.appendChild(rangesInputToValue);
|
||||
rangesContainer.appendChild(rangesDivContainerToValue);
|
||||
|
||||
// Div Color.
|
||||
const rangesDivContainerColor = document.createElement("div");
|
||||
const rangesLabelColor = this.createLabel("Color");
|
||||
const rangesInputColor = this.createInputColor(
|
||||
initialState.color,
|
||||
handleColor
|
||||
);
|
||||
rangesContainerFromValue.appendChild(rangesLabelColor);
|
||||
rangesContainerFromValue.appendChild(rangesInputColor);
|
||||
rangesContainer.appendChild(rangesDivContainerColor);
|
||||
|
||||
// Button delete.
|
||||
const createBtn = document.createElement("a");
|
||||
createBtn.appendChild(
|
||||
fontAwesomeIcon(faPlusCircle, t("Create color range"), {
|
||||
size: "small",
|
||||
color: "#565656"
|
||||
})
|
||||
);
|
||||
|
||||
const handleCreate = () => {
|
||||
if (isValid(state)) onCreate(state);
|
||||
state = initialState;
|
||||
console.log(state);
|
||||
rangesInputFromValue.value = `${state.fromValue || ""}`;
|
||||
rangesInputToValue.value = `${state.toValue || ""}`;
|
||||
rangesInputColor.value = `${state.color}`;
|
||||
};
|
||||
|
||||
createBtn.addEventListener("click", handleCreate);
|
||||
|
||||
rangesContainer.appendChild(createBtn);
|
||||
|
||||
return rangesContainer;
|
||||
}
|
||||
|
||||
private rangeContainer(
|
||||
colorRange: ColorRange,
|
||||
onUpdate: (range: ColorRange) => void,
|
||||
onDelete: () => void
|
||||
): HTMLDivElement {
|
||||
// TODO: Document
|
||||
const state = { ...colorRange };
|
||||
|
||||
const handleFromValue = (value: ColorRange["fromValue"]): void => {
|
||||
state.fromValue = value;
|
||||
onUpdate({ ...state });
|
||||
};
|
||||
const handleToValue = (value: ColorRange["toValue"]): void => {
|
||||
state.toValue = value;
|
||||
onUpdate({ ...state });
|
||||
};
|
||||
const handleColor = (value: ColorRange["color"]): void => {
|
||||
state.color = value;
|
||||
onUpdate({ ...state });
|
||||
};
|
||||
|
||||
const rangesContainer = document.createElement("div");
|
||||
|
||||
// Div From value.
|
||||
const rangesContainerFromValue = document.createElement("div");
|
||||
const rangesLabelFromValue = this.createLabel("From Value");
|
||||
const rangesInputFromValue = this.createInputNumber(
|
||||
colorRange.fromValue,
|
||||
handleFromValue
|
||||
);
|
||||
rangesContainerFromValue.appendChild(rangesLabelFromValue);
|
||||
rangesContainerFromValue.appendChild(rangesInputFromValue);
|
||||
rangesContainer.appendChild(rangesContainerFromValue);
|
||||
|
||||
// Div To Value.
|
||||
const rangesDivContainerToValue = document.createElement("div");
|
||||
const rangesLabelToValue = this.createLabel("To Value");
|
||||
const rangesInputToValue = this.createInputNumber(
|
||||
colorRange.toValue,
|
||||
handleToValue
|
||||
);
|
||||
rangesContainerFromValue.appendChild(rangesLabelToValue);
|
||||
rangesContainerFromValue.appendChild(rangesInputToValue);
|
||||
rangesContainer.appendChild(rangesDivContainerToValue);
|
||||
|
||||
// Div Color.
|
||||
const rangesDivContainerColor = document.createElement("div");
|
||||
const rangesLabelColor = this.createLabel("Color");
|
||||
const rangesInputColor = this.createInputColor(
|
||||
colorRange.color,
|
||||
handleColor
|
||||
);
|
||||
rangesContainerFromValue.appendChild(rangesLabelColor);
|
||||
rangesContainerFromValue.appendChild(rangesInputColor);
|
||||
rangesContainer.appendChild(rangesDivContainerColor);
|
||||
|
||||
// Button delete.
|
||||
const deleteBtn = document.createElement("a");
|
||||
deleteBtn.appendChild(
|
||||
fontAwesomeIcon(faTrashAlt, t("Delete color range"), {
|
||||
size: "small",
|
||||
color: "#565656"
|
||||
})
|
||||
);
|
||||
deleteBtn.addEventListener("click", onDelete);
|
||||
|
||||
rangesContainer.appendChild(deleteBtn);
|
||||
|
||||
return rangesContainer;
|
||||
}
|
||||
|
||||
private createLabel(text: string): HTMLLabelElement {
|
||||
const label = document.createElement("label");
|
||||
label.textContent = t(text);
|
||||
return label;
|
||||
}
|
||||
|
||||
private createInputNumber(
|
||||
value: number | null,
|
||||
onUpdate: (value: number) => void
|
||||
): HTMLInputElement {
|
||||
const input = document.createElement("input");
|
||||
input.type = "number";
|
||||
if (value !== null) input.value = `${value}`;
|
||||
input.addEventListener("change", e => {
|
||||
const value = parseInt((e.target as HTMLInputElement).value);
|
||||
if (!isNaN(value)) onUpdate(value);
|
||||
});
|
||||
|
||||
return input;
|
||||
}
|
||||
|
||||
private createInputColor(
|
||||
value: string | null,
|
||||
onUpdate: (value: string) => void
|
||||
): HTMLInputElement {
|
||||
const input = document.createElement("input");
|
||||
input.type = "color";
|
||||
if (value !== null) input.value = value;
|
||||
input.addEventListener("change", e =>
|
||||
onUpdate((e.target as HTMLInputElement).value)
|
||||
);
|
||||
|
||||
return input;
|
||||
}
|
||||
}
|
||||
|
||||
const svgNS = "http://www.w3.org/2000/svg";
|
||||
|
||||
export default class ColorCloud extends Item<ColorCloudProps> {
|
||||
|
@ -101,4 +412,26 @@ export default class ColorCloud extends Item<ColorCloudProps> {
|
|||
|
||||
return svg;
|
||||
}
|
||||
|
||||
/**
|
||||
* @override function to add or remove inputsGroups those that are not necessary.
|
||||
* Add to:
|
||||
* ColorInputGroup
|
||||
* RangesInputGroup
|
||||
*/
|
||||
public getFormContainer(): FormContainer {
|
||||
return ColorCloud.getFormContainer(this.props);
|
||||
}
|
||||
|
||||
public static getFormContainer(
|
||||
props: Partial<ColorCloudProps>
|
||||
): FormContainer {
|
||||
const formContainer = super.getFormContainer(props);
|
||||
formContainer.removeInputGroup("label");
|
||||
|
||||
formContainer.addInputGroup(new ColorInputGroup("color-cloud", props), 3);
|
||||
formContainer.addInputGroup(new RangesInputGroup("ranges-cloud", props), 4);
|
||||
|
||||
return formContainer;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,13 +7,15 @@ import {
|
|||
linkedVCPropsDecoder,
|
||||
modulePropsDecoder,
|
||||
decodeBase64,
|
||||
stringIsEmpty
|
||||
stringIsEmpty,
|
||||
t
|
||||
} from "../lib";
|
||||
import Item, { ItemType, ItemProps, itemBasePropsDecoder } from "../Item";
|
||||
|
||||
export type DonutGraphProps = {
|
||||
type: ItemType.DONUT_GRAPH;
|
||||
html: string;
|
||||
legendBackgroundColor: string;
|
||||
} & ItemProps &
|
||||
WithModuleProps &
|
||||
LinkedVisualConsoleProps;
|
||||
|
@ -40,6 +42,9 @@ export function donutGraphPropsDecoder(
|
|||
html: !stringIsEmpty(data.html)
|
||||
? data.html
|
||||
: decodeBase64(data.encodedHtml),
|
||||
legendBackgroundColor: stringIsEmpty(data.legendBackgroundColor)
|
||||
? "#000000"
|
||||
: data.legendBackgroundColor,
|
||||
...modulePropsDecoder(data), // Object spread. It will merge the properties of the two objects.
|
||||
...linkedVCPropsDecoder(data) // Object spread. It will merge the properties of the two objects.
|
||||
};
|
||||
|
|
|
@ -3,7 +3,8 @@ import {
|
|||
modulePropsDecoder,
|
||||
parseIntOr,
|
||||
decodeBase64,
|
||||
stringIsEmpty
|
||||
stringIsEmpty,
|
||||
t
|
||||
} from "../lib";
|
||||
import Item, { ItemType, ItemProps, itemBasePropsDecoder } from "../Item";
|
||||
|
||||
|
|
|
@ -5,7 +5,8 @@ import {
|
|||
notEmptyStringOr,
|
||||
stringIsEmpty,
|
||||
decodeBase64,
|
||||
parseBoolean
|
||||
parseBoolean,
|
||||
t
|
||||
} from "../lib";
|
||||
import Item, { ItemProps, itemBasePropsDecoder, ItemType } from "../Item";
|
||||
|
||||
|
@ -59,7 +60,6 @@ export function groupPropsDecoder(data: AnyObject): GroupProps | never {
|
|||
...linkedVCPropsDecoder(data) // Object spread. It will merge the properties of the two objects.
|
||||
};
|
||||
}
|
||||
|
||||
export default class Group extends Item<GroupProps> {
|
||||
protected createDomElement(): HTMLElement {
|
||||
const element = document.createElement("div");
|
||||
|
@ -67,14 +67,35 @@ export default class Group extends Item<GroupProps> {
|
|||
|
||||
if (!this.props.showStatistics && this.props.statusImageSrc !== null) {
|
||||
// Icon with status.
|
||||
element.style.background = `url(${this.props.statusImageSrc}) no-repeat`;
|
||||
element.style.backgroundImage = `url(${this.props.statusImageSrc})`;
|
||||
element.style.backgroundRepeat = "no-repeat";
|
||||
element.style.backgroundSize = "contain";
|
||||
element.style.backgroundPosition = "center";
|
||||
} else if (this.props.showStatistics && this.props.html != null) {
|
||||
// Stats table.
|
||||
element.style.backgroundImage = "none";
|
||||
element.innerHTML = this.props.html;
|
||||
}
|
||||
|
||||
return element;
|
||||
}
|
||||
|
||||
/**
|
||||
* To update the content element.
|
||||
* @override Item.updateDomElement
|
||||
*/
|
||||
protected updateDomElement(element: HTMLElement): void {
|
||||
if (!this.props.showStatistics && this.props.statusImageSrc !== null) {
|
||||
// Icon with status.
|
||||
element.style.backgroundImage = `url(${this.props.statusImageSrc})`;
|
||||
element.style.backgroundRepeat = "no-repeat";
|
||||
element.style.backgroundSize = "contain";
|
||||
element.style.backgroundPosition = "center";
|
||||
element.innerHTML = "";
|
||||
} else if (this.props.showStatistics && this.props.html != null) {
|
||||
// Stats table.
|
||||
element.style.backgroundImage = "none";
|
||||
element.innerHTML = this.props.html;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ import Item, { ItemType, ItemProps, itemBasePropsDecoder } from "../Item";
|
|||
|
||||
export type IconProps = {
|
||||
type: ItemType.ICON;
|
||||
image: string;
|
||||
imageSrc: string; // URL?
|
||||
} & ItemProps &
|
||||
LinkedVisualConsoleProps;
|
||||
|
@ -22,9 +23,14 @@ export function iconPropsDecoder(data: AnyObject): IconProps | never {
|
|||
throw new TypeError("invalid image src.");
|
||||
}
|
||||
|
||||
if (typeof data.image !== "string" || data.image.length === 0) {
|
||||
throw new TypeError("invalid image.");
|
||||
}
|
||||
|
||||
return {
|
||||
...itemBasePropsDecoder(data), // Object spread. It will merge the properties of the two objects.
|
||||
type: ItemType.ICON,
|
||||
image: data.image,
|
||||
imageSrc: data.imageSrc,
|
||||
...linkedVCPropsDecoder(data) // Object spread. It will merge the properties of the two objects.
|
||||
};
|
||||
|
@ -33,11 +39,20 @@ export function iconPropsDecoder(data: AnyObject): IconProps | never {
|
|||
export default class Icon extends Item<IconProps> {
|
||||
protected createDomElement(): HTMLElement {
|
||||
const element = document.createElement("div");
|
||||
element.className = "icon";
|
||||
element.style.background = `url(${this.props.imageSrc}) no-repeat`;
|
||||
element.className = "icon " + this.props.image;
|
||||
element.style.backgroundImage = `url(${this.props.imageSrc})`;
|
||||
element.style.backgroundRepeat = "no-repeat";
|
||||
element.style.backgroundSize = "contain";
|
||||
element.style.backgroundPosition = "center";
|
||||
|
||||
return element;
|
||||
}
|
||||
|
||||
/**
|
||||
* To update the content element.
|
||||
* @override Item.updateDomElement
|
||||
*/
|
||||
protected updateDomElement(element: HTMLElement): void {
|
||||
element.style.backgroundImage = `url(${this.props.imageSrc})`;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,12 @@
|
|||
import { AnyObject, Position, Size, ItemMeta } from "../lib/types";
|
||||
import { parseIntOr, notEmptyStringOr } from "../lib";
|
||||
import {
|
||||
parseIntOr,
|
||||
notEmptyStringOr,
|
||||
debounce,
|
||||
addMovementListener
|
||||
} from "../lib";
|
||||
import Item, { ItemType, ItemProps, itemBasePropsDecoder } from "../Item";
|
||||
import TypedEvent, { Listener, Disposable } from "../lib/TypedEvent";
|
||||
|
||||
interface LineProps extends ItemProps {
|
||||
// Overrided properties.
|
||||
|
@ -63,43 +69,197 @@ export function linePropsDecoder(data: AnyObject): LineProps | never {
|
|||
...props,
|
||||
// Enhance the props extracting the box size and position.
|
||||
// eslint-disable-next-line @typescript-eslint/no-use-before-define
|
||||
...Line.extractBoxSizeAndPosition(props)
|
||||
...Line.extractBoxSizeAndPosition(props.startPosition, props.endPosition)
|
||||
};
|
||||
}
|
||||
|
||||
const svgNS = "http://www.w3.org/2000/svg";
|
||||
|
||||
export interface LineMovedEvent {
|
||||
item: Line;
|
||||
startPosition: LineProps["startPosition"];
|
||||
endPosition: LineProps["endPosition"];
|
||||
}
|
||||
|
||||
export default class Line extends Item<LineProps> {
|
||||
private circleRadius = 8;
|
||||
// To control if the line movement is enabled.
|
||||
private moveMode: boolean = false;
|
||||
// To control if the line is moving.
|
||||
private isMoving: boolean = false;
|
||||
|
||||
// Event manager for moved events.
|
||||
private readonly lineMovedEventManager = new TypedEvent<LineMovedEvent>();
|
||||
// List of references to clean the event listeners.
|
||||
private readonly lineMovedEventDisposables: Disposable[] = [];
|
||||
|
||||
// This function will only run the 2nd arg function after the time
|
||||
// of the first arg have passed after its last execution.
|
||||
private debouncedStartPositionMovementSave = debounce(
|
||||
500, // ms.
|
||||
(x: Position["x"], y: Position["y"]) => {
|
||||
this.isMoving = false;
|
||||
const startPosition = { x, y };
|
||||
// Emit the movement event.
|
||||
this.lineMovedEventManager.emit({
|
||||
item: this,
|
||||
startPosition,
|
||||
endPosition: this.props.endPosition
|
||||
});
|
||||
}
|
||||
);
|
||||
// This property will store the function
|
||||
// to clean the movement listener.
|
||||
private removeStartPositionMovement: Function | null = null;
|
||||
|
||||
/**
|
||||
* Start the movement funtionality for the start position.
|
||||
* @param element Element to move inside its container.
|
||||
*/
|
||||
private initStartPositionMovementListener(
|
||||
element: HTMLElement,
|
||||
container: HTMLElement
|
||||
): void {
|
||||
this.removeStartPositionMovement = addMovementListener(
|
||||
element,
|
||||
(x: Position["x"], y: Position["y"]) => {
|
||||
// Calculate the center of the circle.
|
||||
x += this.circleRadius;
|
||||
y += this.circleRadius;
|
||||
|
||||
const startPosition = { x, y };
|
||||
|
||||
this.isMoving = true;
|
||||
this.props = {
|
||||
...this.props,
|
||||
startPosition
|
||||
};
|
||||
|
||||
// Run the end function.
|
||||
this.debouncedStartPositionMovementSave(x, y);
|
||||
},
|
||||
container
|
||||
);
|
||||
}
|
||||
/**
|
||||
* Stop the movement fun
|
||||
*/
|
||||
private stopStartPositionMovementListener(): void {
|
||||
if (this.removeStartPositionMovement) {
|
||||
this.removeStartPositionMovement();
|
||||
this.removeStartPositionMovement = null;
|
||||
}
|
||||
}
|
||||
|
||||
// This function will only run the 2nd arg function after the time
|
||||
// of the first arg have passed after its last execution.
|
||||
private debouncedEndPositionMovementSave = debounce(
|
||||
500, // ms.
|
||||
(x: Position["x"], y: Position["y"]) => {
|
||||
this.isMoving = false;
|
||||
const endPosition = { x, y };
|
||||
// Emit the movement event.
|
||||
this.lineMovedEventManager.emit({
|
||||
item: this,
|
||||
endPosition,
|
||||
startPosition: this.props.startPosition
|
||||
});
|
||||
}
|
||||
);
|
||||
// This property will store the function
|
||||
// to clean the movement listener.
|
||||
private removeEndPositionMovement: Function | null = null;
|
||||
|
||||
/**
|
||||
* End the movement funtionality for the end position.
|
||||
* @param element Element to move inside its container.
|
||||
*/
|
||||
private initEndPositionMovementListener(
|
||||
element: HTMLElement,
|
||||
container: HTMLElement
|
||||
): void {
|
||||
this.removeEndPositionMovement = addMovementListener(
|
||||
element,
|
||||
(x: Position["x"], y: Position["y"]) => {
|
||||
// Calculate the center of the circle.
|
||||
x += this.circleRadius;
|
||||
y += this.circleRadius;
|
||||
|
||||
this.isMoving = true;
|
||||
this.props = {
|
||||
...this.props,
|
||||
endPosition: { x, y }
|
||||
};
|
||||
|
||||
// Run the end function.
|
||||
this.debouncedEndPositionMovementSave(x, y);
|
||||
},
|
||||
container
|
||||
);
|
||||
}
|
||||
/**
|
||||
* Stop the movement function.
|
||||
*/
|
||||
private stopEndPositionMovementListener(): void {
|
||||
if (this.removeEndPositionMovement) {
|
||||
this.removeEndPositionMovement();
|
||||
this.removeEndPositionMovement = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
public constructor(props: LineProps, meta: ItemMeta) {
|
||||
/*
|
||||
* We need to override the constructor cause we need to obtain
|
||||
* the
|
||||
* box size and position from the start and finish points
|
||||
* of the line.
|
||||
* We need to override the constructor cause we need to obtain the
|
||||
* box size and position from the start and finish points of the line.
|
||||
*/
|
||||
super(
|
||||
{
|
||||
...props,
|
||||
...Line.extractBoxSizeAndPosition(props)
|
||||
...Line.extractBoxSizeAndPosition(
|
||||
props.startPosition,
|
||||
props.endPosition
|
||||
)
|
||||
},
|
||||
{
|
||||
...meta,
|
||||
editMode: false
|
||||
}
|
||||
...meta
|
||||
},
|
||||
true
|
||||
);
|
||||
|
||||
this.moveMode = meta.editMode;
|
||||
this.init();
|
||||
}
|
||||
|
||||
/**
|
||||
* Clasic and protected version of the setter of the `meta` property.
|
||||
* Classic and protected version of the setter of the `props` property.
|
||||
* Useful to override it from children classes.
|
||||
* @param newProps
|
||||
* @override Item.setProps
|
||||
*/
|
||||
public setProps(newProps: LineProps) {
|
||||
super.setProps({
|
||||
...newProps,
|
||||
...Line.extractBoxSizeAndPosition(
|
||||
newProps.startPosition,
|
||||
newProps.endPosition
|
||||
)
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Classic and protected version of the setter of the `meta` property.
|
||||
* Useful to override it from children classes.
|
||||
* @param newMetadata
|
||||
* @override Item.setMeta
|
||||
*/
|
||||
public setMeta(newMetadata: ItemMeta) {
|
||||
this.moveMode = newMetadata.editMode;
|
||||
super.setMeta({
|
||||
...newMetadata,
|
||||
editMode: false
|
||||
lineMode: true
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -112,37 +272,34 @@ export default class Line extends Item<LineProps> {
|
|||
const element: HTMLDivElement = document.createElement("div");
|
||||
element.className = "line";
|
||||
|
||||
const svgNS = "http://www.w3.org/2000/svg";
|
||||
const {
|
||||
x, // Box x
|
||||
y, // Box y
|
||||
width, // Box width
|
||||
height, // Box height
|
||||
lineWidth, // Line thickness
|
||||
startPosition, // Line start position
|
||||
endPosition, // Line end position
|
||||
color // Line color
|
||||
} = this.props;
|
||||
|
||||
const x1 = startPosition.x - x + lineWidth / 2;
|
||||
const y1 = startPosition.y - y + lineWidth / 2;
|
||||
const x2 = endPosition.x - x + lineWidth / 2;
|
||||
const y2 = endPosition.y - y + lineWidth / 2;
|
||||
|
||||
// SVG container.
|
||||
const svg = document.createElementNS(svgNS, "svg");
|
||||
// Set SVG size.
|
||||
svg.setAttribute(
|
||||
"width",
|
||||
(this.props.width + this.props.lineWidth).toString()
|
||||
);
|
||||
svg.setAttribute(
|
||||
"height",
|
||||
(this.props.height + this.props.lineWidth).toString()
|
||||
);
|
||||
svg.setAttribute("width", `${width + lineWidth}`);
|
||||
svg.setAttribute("height", `${height + lineWidth}`);
|
||||
const line = document.createElementNS(svgNS, "line");
|
||||
line.setAttribute(
|
||||
"x1",
|
||||
`${this.props.startPosition.x - this.props.x + this.props.lineWidth / 2}`
|
||||
);
|
||||
line.setAttribute(
|
||||
"y1",
|
||||
`${this.props.startPosition.y - this.props.y + this.props.lineWidth / 2}`
|
||||
);
|
||||
line.setAttribute(
|
||||
"x2",
|
||||
`${this.props.endPosition.x - this.props.x + this.props.lineWidth / 2}`
|
||||
);
|
||||
line.setAttribute(
|
||||
"y2",
|
||||
`${this.props.endPosition.y - this.props.y + this.props.lineWidth / 2}`
|
||||
);
|
||||
line.setAttribute("stroke", this.props.color || "black");
|
||||
line.setAttribute("stroke-width", this.props.lineWidth.toString());
|
||||
line.setAttribute("x1", `${x1}`);
|
||||
line.setAttribute("y1", `${y1}`);
|
||||
line.setAttribute("x2", `${x2}`);
|
||||
line.setAttribute("y2", `${y2}`);
|
||||
line.setAttribute("stroke", color || "black");
|
||||
line.setAttribute("stroke-width", `${lineWidth}`);
|
||||
|
||||
svg.append(line);
|
||||
element.append(svg);
|
||||
|
@ -150,17 +307,217 @@ export default class Line extends Item<LineProps> {
|
|||
return element;
|
||||
}
|
||||
|
||||
protected updateDomElement(element: HTMLElement): void {
|
||||
const {
|
||||
x, // Box x
|
||||
y, // Box y
|
||||
width, // Box width
|
||||
height, // Box height
|
||||
lineWidth, // Line thickness
|
||||
startPosition, // Line start position
|
||||
endPosition, // Line end position
|
||||
color // Line color
|
||||
} = this.props;
|
||||
|
||||
const x1 = startPosition.x - x + lineWidth / 2;
|
||||
const y1 = startPosition.y - y + lineWidth / 2;
|
||||
const x2 = endPosition.x - x + lineWidth / 2;
|
||||
const y2 = endPosition.y - y + lineWidth / 2;
|
||||
|
||||
const svgs = element.getElementsByTagName("svg");
|
||||
|
||||
if (svgs.length > 0) {
|
||||
const svg = svgs.item(0);
|
||||
|
||||
if (svg != null) {
|
||||
// Set SVG size.
|
||||
svg.setAttribute("width", `${width + lineWidth}`);
|
||||
svg.setAttribute("height", `${height + lineWidth}`);
|
||||
|
||||
const lines = svg.getElementsByTagNameNS(svgNS, "line");
|
||||
|
||||
if (lines.length > 0) {
|
||||
const line = lines.item(0);
|
||||
|
||||
if (line != null) {
|
||||
line.setAttribute("x1", `${x1}`);
|
||||
line.setAttribute("y1", `${y1}`);
|
||||
line.setAttribute("x2", `${x2}`);
|
||||
line.setAttribute("y2", `${y2}`);
|
||||
line.setAttribute("stroke", color || "black");
|
||||
line.setAttribute("stroke-width", `${lineWidth}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (this.moveMode) {
|
||||
const startIsLeft = startPosition.x - endPosition.x <= 0;
|
||||
const startIsTop = startPosition.y - endPosition.y <= 0;
|
||||
|
||||
let startCircle: HTMLElement = document.createElement("div");
|
||||
let endCircle: HTMLElement = document.createElement("div");
|
||||
|
||||
if (this.isMoving) {
|
||||
const circlesStart = element.getElementsByClassName(
|
||||
"visual-console-item-line-circle-start"
|
||||
);
|
||||
if (circlesStart.length > 0) {
|
||||
const circle = circlesStart.item(0) as HTMLElement;
|
||||
if (circle) startCircle = circle;
|
||||
}
|
||||
const circlesEnd = element.getElementsByClassName(
|
||||
"visual-console-item-line-circle-end"
|
||||
);
|
||||
if (circlesEnd.length > 0) {
|
||||
const circle = circlesEnd.item(0) as HTMLElement;
|
||||
if (circle) endCircle = circle;
|
||||
}
|
||||
}
|
||||
|
||||
startCircle.classList.add(
|
||||
"visual-console-item-line-circle",
|
||||
"visual-console-item-line-circle-start"
|
||||
);
|
||||
startCircle.style.width = `${this.circleRadius * 2}px`;
|
||||
startCircle.style.height = `${this.circleRadius * 2}px`;
|
||||
startCircle.style.borderRadius = "50%";
|
||||
startCircle.style.backgroundColor = `${color}`;
|
||||
startCircle.style.position = "absolute";
|
||||
startCircle.style.left = startIsLeft
|
||||
? `-${this.circleRadius}px`
|
||||
: `${width + lineWidth - this.circleRadius}px`;
|
||||
startCircle.style.top = startIsTop
|
||||
? `-${this.circleRadius}px`
|
||||
: `${height + lineWidth - this.circleRadius}px`;
|
||||
|
||||
endCircle.classList.add(
|
||||
"visual-console-item-line-circle",
|
||||
"visual-console-item-line-circle-end"
|
||||
);
|
||||
endCircle.style.width = `${this.circleRadius * 2}px`;
|
||||
endCircle.style.height = `${this.circleRadius * 2}px`;
|
||||
endCircle.style.borderRadius = "50%";
|
||||
endCircle.style.backgroundColor = `${color}`;
|
||||
endCircle.style.position = "absolute";
|
||||
endCircle.style.left = startIsLeft
|
||||
? `${width + lineWidth - 8}px`
|
||||
: `-${this.circleRadius}px`;
|
||||
endCircle.style.top = startIsTop
|
||||
? `${height + lineWidth - this.circleRadius}px`
|
||||
: `-${this.circleRadius}px`;
|
||||
|
||||
if (element.parentElement !== null) {
|
||||
const circles = element.parentElement.getElementsByClassName(
|
||||
"visual-console-item-line-circle"
|
||||
);
|
||||
while (circles.length > 0) {
|
||||
const circle = circles.item(0);
|
||||
if (circle) circle.remove();
|
||||
}
|
||||
|
||||
element.parentElement.appendChild(startCircle);
|
||||
element.parentElement.appendChild(endCircle);
|
||||
}
|
||||
|
||||
// Init the movement listeners.
|
||||
this.initStartPositionMovementListener(startCircle, this.elementRef
|
||||
.parentElement as HTMLElement);
|
||||
this.initEndPositionMovementListener(endCircle, this.elementRef
|
||||
.parentElement as HTMLElement);
|
||||
} else if (!this.moveMode) {
|
||||
this.stopStartPositionMovementListener();
|
||||
// Remove circles.
|
||||
if (element.parentElement !== null) {
|
||||
const circles = element.parentElement.getElementsByClassName(
|
||||
"visual-console-item-line-circle"
|
||||
);
|
||||
|
||||
while (circles.length > 0) {
|
||||
const circle = circles.item(0);
|
||||
if (circle) circle.remove();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
this.stopStartPositionMovementListener();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract the size and position of the box from
|
||||
* the start and the finish of the line.
|
||||
* @param props Item properties.
|
||||
*/
|
||||
public static extractBoxSizeAndPosition(props: LineProps): Size & Position {
|
||||
public static extractBoxSizeAndPosition(
|
||||
startPosition: Position,
|
||||
endPosition: Position
|
||||
): Size & Position {
|
||||
return {
|
||||
width: Math.abs(props.startPosition.x - props.endPosition.x),
|
||||
height: Math.abs(props.startPosition.y - props.endPosition.y),
|
||||
x: Math.min(props.startPosition.x, props.endPosition.x),
|
||||
y: Math.min(props.startPosition.y, props.endPosition.y)
|
||||
width: Math.abs(startPosition.x - endPosition.x),
|
||||
height: Math.abs(startPosition.y - endPosition.y),
|
||||
x: Math.min(startPosition.x, endPosition.x),
|
||||
y: Math.min(startPosition.y, endPosition.y)
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the position into the properties and move the DOM container.
|
||||
* @param x Horizontal axis position.
|
||||
* @param y Vertical axis position.
|
||||
* @override item function
|
||||
*/
|
||||
public move(x: number, y: number): void {
|
||||
super.moveElement(x, y);
|
||||
const startIsLeft =
|
||||
this.props.startPosition.x - this.props.endPosition.x <= 0;
|
||||
const startIsTop =
|
||||
this.props.startPosition.y - this.props.endPosition.y <= 0;
|
||||
|
||||
const start = {
|
||||
x: startIsLeft ? x : this.props.width + x,
|
||||
y: startIsTop ? y : this.props.height + y
|
||||
};
|
||||
|
||||
const end = {
|
||||
x: startIsLeft ? this.props.width + x : x,
|
||||
y: startIsTop ? this.props.height + y : y
|
||||
};
|
||||
|
||||
this.props = {
|
||||
...this.props,
|
||||
startPosition: start,
|
||||
endPosition: end
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* To remove the event listeners and the elements from the DOM.
|
||||
* @override Item.remove
|
||||
*/
|
||||
public remove(): void {
|
||||
// Clear the item's event listeners.
|
||||
this.stopStartPositionMovementListener();
|
||||
// Call the parent's .remove()
|
||||
super.remove();
|
||||
}
|
||||
|
||||
/**
|
||||
* To add an event handler to the movement of visual console elements.
|
||||
* @param listener Function which is going to be executed when a linked console is moved.
|
||||
*
|
||||
* @override Item.onMoved
|
||||
*/
|
||||
public onLineMovementFinished(
|
||||
listener: Listener<LineMovedEvent>
|
||||
): Disposable {
|
||||
/*
|
||||
* The '.on' function returns a function which will clean the event
|
||||
* listener when executed. We store all the 'dispose' functions to
|
||||
* call them when the item should be cleared.
|
||||
*/
|
||||
const disposable = this.lineMovedEventManager.on(listener);
|
||||
this.lineMovedEventDisposables.push(disposable);
|
||||
|
||||
return disposable;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,17 +7,53 @@ import {
|
|||
linkedVCPropsDecoder,
|
||||
modulePropsDecoder,
|
||||
decodeBase64,
|
||||
stringIsEmpty
|
||||
stringIsEmpty,
|
||||
parseIntOr
|
||||
} from "../lib";
|
||||
import Item, { ItemType, ItemProps, itemBasePropsDecoder } from "../Item";
|
||||
|
||||
export type ModuleGraphProps = {
|
||||
type: ItemType.MODULE_GRAPH;
|
||||
html: string;
|
||||
backgroundType: "white" | "black" | "transparent";
|
||||
graphType: "line" | "area";
|
||||
period: number | null;
|
||||
customGraphId: number | null;
|
||||
} & ItemProps &
|
||||
WithModuleProps &
|
||||
LinkedVisualConsoleProps;
|
||||
|
||||
/**
|
||||
* Extract a valid enum value from a raw unknown value.
|
||||
* @param backgroundType Raw value.
|
||||
*/
|
||||
const parseBackgroundType = (
|
||||
backgroundType: unknown
|
||||
): ModuleGraphProps["backgroundType"] => {
|
||||
switch (backgroundType) {
|
||||
case "white":
|
||||
case "black":
|
||||
case "transparent":
|
||||
return backgroundType;
|
||||
default:
|
||||
return "transparent";
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Extract a valid enum value from a raw unknown value.
|
||||
* @param graphType Raw value.
|
||||
*/
|
||||
const parseGraphType = (graphType: unknown): ModuleGraphProps["graphType"] => {
|
||||
switch (graphType) {
|
||||
case "line":
|
||||
case "area":
|
||||
return graphType;
|
||||
default:
|
||||
return "line";
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Build a valid typed object from a raw object.
|
||||
* This will allow us to ensure the type safety.
|
||||
|
@ -40,86 +76,33 @@ export function moduleGraphPropsDecoder(
|
|||
html: !stringIsEmpty(data.html)
|
||||
? data.html
|
||||
: decodeBase64(data.encodedHtml),
|
||||
backgroundType: parseBackgroundType(data.backgroundType),
|
||||
period: parseIntOr(data.period, null),
|
||||
graphType: parseGraphType(data.graphType),
|
||||
customGraphId: parseIntOr(data.customGraphId, null),
|
||||
...modulePropsDecoder(data), // Object spread. It will merge the properties of the two objects.
|
||||
...linkedVCPropsDecoder(data) // Object spread. It will merge the properties of the two objects.
|
||||
};
|
||||
}
|
||||
|
||||
export default class ModuleGraph extends Item<ModuleGraphProps> {
|
||||
/**
|
||||
* @override Item.resizeElement.
|
||||
* Resize the DOM content container.
|
||||
* We need to override the resize function cause this item's height
|
||||
* is larger than the configured and the graph is over the label.
|
||||
* @param width
|
||||
* @param height
|
||||
*/
|
||||
protected resizeElement(width: number): void {
|
||||
super.resizeElement(width, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @override Item.initResizementListener. To disable the functionality.
|
||||
* Start the resizement funtionality.
|
||||
* @param element Element to move inside its container.
|
||||
*/
|
||||
protected initResizementListener(): void {
|
||||
// No-Op. Disable the resizement functionality for this item.
|
||||
}
|
||||
|
||||
protected createDomElement(): HTMLElement {
|
||||
const element = document.createElement("div");
|
||||
element.className = "module-graph";
|
||||
element.innerHTML = this.props.html;
|
||||
|
||||
// Remove the overview graph.
|
||||
const legendP = element.getElementsByTagName("p");
|
||||
for (let i = 0; i < legendP.length; i++) {
|
||||
legendP[i].style.margin = "0px";
|
||||
}
|
||||
|
||||
// Remove the overview graph.
|
||||
const overviewGraphs = element.getElementsByClassName("overview_graph");
|
||||
for (let i = 0; i < overviewGraphs.length; i++) {
|
||||
overviewGraphs[i].remove();
|
||||
}
|
||||
|
||||
// Hack to execute the JS after the HTML is added to the DOM.
|
||||
const scripts = element.getElementsByTagName("script");
|
||||
for (let i = 0; i < scripts.length; i++) {
|
||||
if (scripts[i].src.length === 0) {
|
||||
setTimeout(() => {
|
||||
try {
|
||||
eval(scripts[i].innerHTML.trim());
|
||||
} catch (ignored) {} // eslint-disable-line no-empty
|
||||
}, 0);
|
||||
}
|
||||
}
|
||||
element.style.backgroundImage = `url(${this.props.html})`;
|
||||
element.style.backgroundRepeat = "no-repeat";
|
||||
element.style.backgroundSize = `${this.props.width}px ${
|
||||
this.props.height
|
||||
}px`;
|
||||
|
||||
return element;
|
||||
}
|
||||
|
||||
protected updateDomElement(element: HTMLElement): void {
|
||||
element.innerHTML = this.props.html;
|
||||
|
||||
// Remove the overview graph.
|
||||
const legendP = element.getElementsByTagName("p");
|
||||
for (let i = 0; i < legendP.length; i++) {
|
||||
legendP[i].style.margin = "0px";
|
||||
}
|
||||
|
||||
// Remove the overview graph.
|
||||
const overviewGraphs = element.getElementsByClassName("overview_graph");
|
||||
for (let i = 0; i < overviewGraphs.length; i++) {
|
||||
overviewGraphs[i].remove();
|
||||
}
|
||||
|
||||
// Hack to execute the JS after the HTML is added to the DOM.
|
||||
const scripts = element.getElementsByTagName("script");
|
||||
for (let i = 0; i < scripts.length; i++) {
|
||||
if (scripts[i].src.length === 0) {
|
||||
eval(scripts[i].innerHTML.trim());
|
||||
}
|
||||
}
|
||||
element.style.backgroundImage = `url(${this.props.html})`;
|
||||
element.style.backgroundRepeat = "no-repeat";
|
||||
element.style.backgroundSize = `${this.props.width}px ${
|
||||
this.props.height
|
||||
}px`;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -112,8 +112,6 @@ export default class Percentile extends Item<PercentileProps> {
|
|||
const progress = this.getProgress();
|
||||
// Main element.
|
||||
const element = document.createElement("div");
|
||||
// SVG container.
|
||||
const svg = document.createElementNS(svgNS, "svg");
|
||||
|
||||
var formatValue;
|
||||
if (this.props.value != null) {
|
||||
|
@ -124,30 +122,36 @@ export default class Percentile extends Item<PercentileProps> {
|
|||
}
|
||||
}
|
||||
|
||||
// SVG container.
|
||||
const svg = document.createElementNS(svgNS, "svg");
|
||||
|
||||
switch (this.props.percentileType) {
|
||||
case "progress-bar":
|
||||
{
|
||||
const backgroundRect = document.createElementNS(svgNS, "rect");
|
||||
backgroundRect.setAttribute("fill", colors.background);
|
||||
backgroundRect.setAttribute("fill-opacity", "0.5");
|
||||
backgroundRect.setAttribute("width", "100");
|
||||
backgroundRect.setAttribute("height", "20");
|
||||
backgroundRect.setAttribute("width", "100%");
|
||||
backgroundRect.setAttribute("height", "100%");
|
||||
backgroundRect.setAttribute("rx", "5");
|
||||
backgroundRect.setAttribute("ry", "5");
|
||||
const progressRect = document.createElementNS(svgNS, "rect");
|
||||
progressRect.setAttribute("fill", colors.progress);
|
||||
progressRect.setAttribute("fill-opacity", "1");
|
||||
progressRect.setAttribute("width", `${progress}`);
|
||||
progressRect.setAttribute("height", "20");
|
||||
progressRect.setAttribute("width", `${progress}%`);
|
||||
progressRect.setAttribute("height", "100%");
|
||||
progressRect.setAttribute("rx", "5");
|
||||
progressRect.setAttribute("ry", "5");
|
||||
const text = document.createElementNS(svgNS, "text");
|
||||
text.setAttribute("text-anchor", "middle");
|
||||
text.setAttribute("alignment-baseline", "middle");
|
||||
text.setAttribute("font-size", "12");
|
||||
text.setAttribute("font-size", "15");
|
||||
text.setAttribute("font-family", "arial");
|
||||
text.setAttribute("font-weight", "bold");
|
||||
text.setAttribute("transform", "translate(50 11)");
|
||||
text.setAttribute(
|
||||
"transform",
|
||||
`translate(${this.props.width / 2}, 17.5)`
|
||||
);
|
||||
text.setAttribute("fill", colors.text);
|
||||
|
||||
if (this.props.valueType === "value") {
|
||||
|
@ -160,8 +164,8 @@ export default class Percentile extends Item<PercentileProps> {
|
|||
text.textContent = `${progress}%`;
|
||||
}
|
||||
|
||||
// Auto resize SVG using the view box magic: https://css-tricks.com/scale-svg/
|
||||
svg.setAttribute("viewBox", "0 0 100 20");
|
||||
svg.setAttribute("width", "100%");
|
||||
svg.setAttribute("height", "100%");
|
||||
svg.append(backgroundRect, progressRect, text);
|
||||
}
|
||||
break;
|
||||
|
@ -257,11 +261,51 @@ export default class Percentile extends Item<PercentileProps> {
|
|||
break;
|
||||
}
|
||||
|
||||
element.append(svg);
|
||||
if (svg !== null) element.append(svg);
|
||||
|
||||
return element;
|
||||
}
|
||||
|
||||
/**
|
||||
* To update the content element.
|
||||
* @override Item.updateDomElement
|
||||
*/
|
||||
protected updateDomElement(element: HTMLElement): void {
|
||||
if (this.meta.isBeingResized === false) {
|
||||
this.resizeElement(this.props.width, this.props.height);
|
||||
}
|
||||
element.innerHTML = this.createDomElement().innerHTML;
|
||||
}
|
||||
|
||||
/**
|
||||
* To update the content element.
|
||||
* @override Item.updateDomElement
|
||||
*/
|
||||
protected resizeElement(width: number, height: number): void {
|
||||
if (this.props.percentileType === "progress-bar") {
|
||||
super.resizeElement(width, 35);
|
||||
} else {
|
||||
super.resizeElement(width, width);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* To update the content element.
|
||||
* @override Item.updateDomElement
|
||||
*/
|
||||
public resize(width: number): void {
|
||||
this.resizeElement(width, width);
|
||||
let height = this.props.maxValue || 0;
|
||||
if (this.props.percentileType === "progress-bar") {
|
||||
height = 35;
|
||||
}
|
||||
super.setProps({
|
||||
...this.props, // Object spread: http://es6-features.org/#SpreadOperator
|
||||
width,
|
||||
height
|
||||
});
|
||||
}
|
||||
|
||||
private getProgress(): number {
|
||||
const minValue = this.props.minValue || 0;
|
||||
const maxValue = this.props.maxValue || 100;
|
||||
|
|
|
@ -3,9 +3,16 @@ import {
|
|||
stringIsEmpty,
|
||||
notEmptyStringOr,
|
||||
decodeBase64,
|
||||
parseIntOr
|
||||
parseIntOr,
|
||||
t
|
||||
} from "../lib";
|
||||
import Item, { ItemType, ItemProps, itemBasePropsDecoder } from "../Item";
|
||||
import { FormContainer, InputGroup } from "../Form";
|
||||
import fontAwesomeIcon from "../lib/FontAwesomeIcon";
|
||||
import {
|
||||
faCircleNotch,
|
||||
faExclamationCircle
|
||||
} from "@fortawesome/free-solid-svg-icons";
|
||||
|
||||
export type ServiceProps = {
|
||||
type: ItemType.SERVICE;
|
||||
|
@ -67,4 +74,19 @@ export default class Service extends Item<ServiceProps> {
|
|||
|
||||
return element;
|
||||
}
|
||||
|
||||
/**
|
||||
* To update the content element.
|
||||
* @override Item.updateDomElement
|
||||
*/
|
||||
protected updateDomElement(element: HTMLElement): void {
|
||||
if (this.props.statusImageSrc !== null) {
|
||||
element.style.background = `url(${this.props.statusImageSrc}) no-repeat`;
|
||||
element.style.backgroundSize = "contain";
|
||||
element.style.backgroundPosition = "center";
|
||||
element.innerHTML = "";
|
||||
} else if (this.props.encodedTitle !== null) {
|
||||
element.innerHTML = decodeBase64(this.props.encodedTitle);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -114,11 +114,10 @@ export default class SimpleValue extends Item<SimpleValueProps> {
|
|||
}
|
||||
|
||||
/**
|
||||
* @override Item.createLabelDomElement
|
||||
* Create a new label for the visual console item.
|
||||
* @return Item label.
|
||||
*/
|
||||
protected createLabelDomElement(): HTMLElement {
|
||||
* Generate a element size
|
||||
* using the current size and the default values.
|
||||
* @return The size.
|
||||
*/ protected createLabelDomElement(): HTMLElement {
|
||||
const element = document.createElement("div");
|
||||
element.className = "visual-console-item-label";
|
||||
// Always return an empty label.
|
||||
|
|
|
@ -18,7 +18,8 @@ export type StaticGraphProps = {
|
|||
statusImageSrc: string | null; // URL?
|
||||
lastValue: string | null;
|
||||
} & ItemProps &
|
||||
(WithModuleProps | LinkedVisualConsoleProps);
|
||||
WithModuleProps &
|
||||
LinkedVisualConsoleProps;
|
||||
|
||||
/**
|
||||
* Extract a valid enum value from a raw unknown value.
|
||||
|
@ -70,7 +71,8 @@ export default class StaticGraph extends Item<StaticGraphProps> {
|
|||
const imgSrc = this.props.statusImageSrc || this.props.imageSrc;
|
||||
const element = document.createElement("div");
|
||||
element.className = "static-graph";
|
||||
element.style.background = `url(${imgSrc}) no-repeat`;
|
||||
element.style.backgroundImage = `url(${imgSrc})`;
|
||||
element.style.backgroundRepeat = "no-repeat";
|
||||
element.style.backgroundSize = "contain";
|
||||
element.style.backgroundPosition = "center";
|
||||
|
||||
|
@ -86,4 +88,13 @@ export default class StaticGraph extends Item<StaticGraphProps> {
|
|||
|
||||
return element;
|
||||
}
|
||||
|
||||
/**
|
||||
* To update the content element.
|
||||
* @override Item.updateDomElement
|
||||
*/
|
||||
protected updateDomElement(element: HTMLElement): void {
|
||||
const imgSrc = this.props.statusImageSrc || this.props.imageSrc;
|
||||
element.style.backgroundImage = `url(${imgSrc})`;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,43 @@
|
|||
/* Styles for the solid icons */
|
||||
|
||||
.fa {
|
||||
display: inline-block;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.fa,
|
||||
.fa > svg,
|
||||
.fa.medium,
|
||||
.fa.medium > svg {
|
||||
width: 28px;
|
||||
height: 28px;
|
||||
}
|
||||
|
||||
.fa.fa-small,
|
||||
.fa.fa-small > svg {
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
}
|
||||
|
||||
.fa.fa-large,
|
||||
.fa.fa-large > svg {
|
||||
width: 44px;
|
||||
height: 44px;
|
||||
}
|
||||
|
||||
.fa-spin {
|
||||
animation: fa-spin 2s infinite linear;
|
||||
}
|
||||
|
||||
.fa-pulse {
|
||||
animation: fa-spin 1s infinite steps(8);
|
||||
}
|
||||
|
||||
@keyframes fa-spin {
|
||||
0% {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
100% {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,49 @@
|
|||
import { IconDefinition } from "@fortawesome/free-solid-svg-icons";
|
||||
import "./FontAwesomeIcon.styles.css";
|
||||
|
||||
const svgNS = "http://www.w3.org/2000/svg";
|
||||
|
||||
interface ExtraProps {
|
||||
size?: "small" | "medium" | "large";
|
||||
color?: string;
|
||||
spin?: boolean;
|
||||
pulse?: boolean;
|
||||
}
|
||||
|
||||
const fontAwesomeIcon = (
|
||||
iconDefinition: IconDefinition,
|
||||
title: string,
|
||||
{ size, color, spin, pulse }: ExtraProps = {}
|
||||
): HTMLElement => {
|
||||
const container = document.createElement("figure");
|
||||
container.title = title;
|
||||
container.className = `fa fa-${iconDefinition.iconName}`;
|
||||
|
||||
if (size) container.classList.add(`fa-${size}`);
|
||||
|
||||
if (spin) container.classList.add("fa-spin");
|
||||
else if (pulse) container.classList.add("fa-pulse");
|
||||
|
||||
const icon = document.createElementNS(svgNS, "svg");
|
||||
// Auto resize SVG using the view box magic: https://css-tricks.com/scale-svg/
|
||||
icon.setAttribute(
|
||||
"viewBox",
|
||||
`0 0 ${iconDefinition.icon[0]} ${iconDefinition.icon[1]}`
|
||||
);
|
||||
if (color) icon.setAttribute("fill", color);
|
||||
|
||||
// Path
|
||||
const path = document.createElementNS(svgNS, "path");
|
||||
const pathData =
|
||||
typeof iconDefinition.icon[4] === "string"
|
||||
? iconDefinition.icon[4]
|
||||
: iconDefinition.icon[4][0];
|
||||
path.setAttribute("d", pathData);
|
||||
|
||||
icon.appendChild(path);
|
||||
container.appendChild(icon);
|
||||
|
||||
return container;
|
||||
};
|
||||
|
||||
export default fontAwesomeIcon;
|
|
@ -0,0 +1,36 @@
|
|||
.autocomplete {
|
||||
/*the container must be positioned relative:*/
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
}
|
||||
.autocomplete input {
|
||||
/*background: pink;*/
|
||||
}
|
||||
.autocomplete-items {
|
||||
border: 1px solid #d4d4d4;
|
||||
border-bottom: none;
|
||||
border-top: none;
|
||||
/*position the autocomplete items to be the same width as the container:*/
|
||||
position: absolute;
|
||||
z-index: 1;
|
||||
overflow: auto;
|
||||
max-height: 150px;
|
||||
max-width: 250px;
|
||||
}
|
||||
.autocomplete-items div {
|
||||
width: 100%;
|
||||
padding: 10px;
|
||||
cursor: pointer;
|
||||
background-color: #fff;
|
||||
border-bottom: 1px solid #d4d4d4;
|
||||
border-top: 1px solid #d4d4d4;
|
||||
}
|
||||
.autocomplete-items div:hover {
|
||||
width: 100%;
|
||||
background-color: #e9e9e9;
|
||||
}
|
||||
.autocomplete-active {
|
||||
/*when navigating through the items using the arrow keys:*/
|
||||
background-color: DodgerBlue !important;
|
||||
color: #ffffff;
|
||||
}
|
Binary file not shown.
After Width: | Height: | Size: 376 B |
|
@ -10,6 +10,11 @@ import {
|
|||
ItemMeta
|
||||
} from "./types";
|
||||
|
||||
import helpTipIcon from "./help-tip.png";
|
||||
import fontAwesomeIcon from "./FontAwesomeIcon";
|
||||
import { faPencilAlt, faListAlt } from "@fortawesome/free-solid-svg-icons";
|
||||
import "./autocomplete.css";
|
||||
|
||||
/**
|
||||
* Return a number or a default value from a raw value.
|
||||
* @param value Raw value from which we will try to extract a valid number.
|
||||
|
@ -168,7 +173,7 @@ export function sizePropsDecoder(data: AnyObject): Size | never {
|
|||
*/
|
||||
export function agentPropsDecoder(data: AnyObject): WithAgentProps {
|
||||
const agentProps: WithAgentProps = {
|
||||
agentId: parseIntOr(data.agent, null),
|
||||
agentId: parseIntOr(data.agentId, null),
|
||||
agentName: notEmptyStringOr(data.agentName, null),
|
||||
agentAlias: notEmptyStringOr(data.agentAlias, null),
|
||||
agentDescription: notEmptyStringOr(data.agentDescription, null),
|
||||
|
@ -206,13 +211,6 @@ export function modulePropsDecoder(data: AnyObject): WithModuleProps {
|
|||
export function linkedVCPropsDecoder(
|
||||
data: AnyObject
|
||||
): LinkedVisualConsoleProps | never {
|
||||
// Object destructuring: http://es6-features.org/#ObjectMatchingShorthandNotation
|
||||
const {
|
||||
metaconsoleId,
|
||||
linkedLayoutId: id,
|
||||
linkedLayoutAgentId: agentId
|
||||
} = data;
|
||||
|
||||
let linkedLayoutStatusProps: LinkedVisualConsolePropsStatus = {
|
||||
linkedLayoutStatusType: "default"
|
||||
};
|
||||
|
@ -251,18 +249,11 @@ export function linkedVCPropsDecoder(
|
|||
}
|
||||
}
|
||||
|
||||
const linkedLayoutBaseProps = {
|
||||
linkedLayoutId: parseIntOr(id, null),
|
||||
linkedLayoutAgentId: parseIntOr(agentId, null),
|
||||
return {
|
||||
linkedLayoutId: parseIntOr(data.linkedLayoutId, null),
|
||||
linkedLayoutNodeId: parseIntOr(data.linkedLayoutNodeId, null),
|
||||
...linkedLayoutStatusProps // Object spread: http://es6-features.org/#SpreadOperator
|
||||
};
|
||||
|
||||
return metaconsoleId != null
|
||||
? {
|
||||
metaconsoleId,
|
||||
...linkedLayoutBaseProps // Object spread: http://es6-features.org/#SpreadOperator
|
||||
}
|
||||
: linkedLayoutBaseProps;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -284,7 +275,11 @@ export function itemMetaDecoder(data: UnknownObject): ItemMeta | never {
|
|||
editMode: parseBoolean(data.editMode),
|
||||
isFromCache: parseBoolean(data.isFromCache),
|
||||
isFetching: false,
|
||||
isUpdating: false
|
||||
isUpdating: false,
|
||||
isBeingMoved: false,
|
||||
isBeingResized: false,
|
||||
isSelected: false,
|
||||
lineMode: false
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -412,10 +407,15 @@ export function debounce<T>(delay: number, fn: (...args: T[]) => void) {
|
|||
* Retrieve the offset of an element relative to the page.
|
||||
* @param el Node used to calculate the offset.
|
||||
*/
|
||||
function getOffset(el: HTMLElement | null) {
|
||||
function getOffset(el: HTMLElement | null, parent?: HTMLElement) {
|
||||
let x = 0;
|
||||
let y = 0;
|
||||
while (el && !Number.isNaN(el.offsetLeft) && !Number.isNaN(el.offsetTop)) {
|
||||
while (
|
||||
el &&
|
||||
!Number.isNaN(el.offsetLeft) &&
|
||||
!Number.isNaN(el.offsetTop) &&
|
||||
el !== parent
|
||||
) {
|
||||
x += el.offsetLeft - el.scrollLeft;
|
||||
y += el.offsetTop - el.scrollTop;
|
||||
el = el.offsetParent as HTMLElement | null;
|
||||
|
@ -428,14 +428,17 @@ function getOffset(el: HTMLElement | null) {
|
|||
*
|
||||
* @param element Element to move.
|
||||
* @param onMoved Function to execute when the element moves.
|
||||
* @param altContainer Alternative element to contain the moved element.
|
||||
*
|
||||
* @return A function which will clean the event handlers when executed.
|
||||
*/
|
||||
export function addMovementListener(
|
||||
element: HTMLElement,
|
||||
onMoved: (x: Position["x"], y: Position["y"]) => void
|
||||
onMoved: (x: Position["x"], y: Position["y"]) => void,
|
||||
altContainer?: HTMLElement
|
||||
): Function {
|
||||
const container = element.parentElement as HTMLElement;
|
||||
const container = altContainer || (element.parentElement as HTMLElement);
|
||||
|
||||
// Store the initial draggable state.
|
||||
const isDraggable = element.draggable;
|
||||
// Init the coordinates.
|
||||
|
@ -457,13 +460,9 @@ export function addMovementListener(
|
|||
let borderFix = Number.parseInt(borderWidth) * 2;
|
||||
|
||||
// Will run onMoved 32ms after its last execution.
|
||||
const debouncedMovement = debounce(32, (x: Position["x"], y: Position["y"]) =>
|
||||
onMoved(x, y)
|
||||
);
|
||||
const debouncedMovement = debounce(32, onMoved);
|
||||
// Will run onMoved one time max every 16ms.
|
||||
const throttledMovement = throttle(16, (x: Position["x"], y: Position["y"]) =>
|
||||
onMoved(x, y)
|
||||
);
|
||||
const throttledMovement = throttle(16, onMoved);
|
||||
|
||||
const handleMove = (e: MouseEvent) => {
|
||||
// Calculate the new element coordinates.
|
||||
|
@ -546,6 +545,9 @@ export function addMovementListener(
|
|||
document.body.style.userSelect = "auto";
|
||||
};
|
||||
const handleStart = (e: MouseEvent) => {
|
||||
// Avoid starting the movement on right click.
|
||||
if (e.button === 2) return;
|
||||
|
||||
e.stopPropagation();
|
||||
|
||||
// Disable the drag temporarily.
|
||||
|
@ -553,8 +555,10 @@ export function addMovementListener(
|
|||
|
||||
// Store the difference between the cursor and
|
||||
// the initial coordinates of the element.
|
||||
lastX = element.offsetLeft;
|
||||
lastY = element.offsetTop;
|
||||
const elementOffset = getOffset(element, container);
|
||||
lastX = elementOffset.left;
|
||||
lastY = elementOffset.top;
|
||||
|
||||
// Store the mouse position.
|
||||
lastMouseX = e.pageX;
|
||||
lastMouseY = e.pageY;
|
||||
|
@ -635,15 +639,9 @@ export function addResizementListener(
|
|||
let borderFix = Number.parseInt(borderWidth);
|
||||
|
||||
// Will run onResized 32ms after its last execution.
|
||||
const debouncedResizement = debounce(
|
||||
32,
|
||||
(width: Size["width"], height: Size["height"]) => onResized(width, height)
|
||||
);
|
||||
const debouncedResizement = debounce(32, onResized);
|
||||
// Will run onResized one time max every 16ms.
|
||||
const throttledResizement = throttle(
|
||||
16,
|
||||
(width: Size["width"], height: Size["height"]) => onResized(width, height)
|
||||
);
|
||||
const throttledResizement = throttle(16, onResized);
|
||||
|
||||
const handleResize = (e: MouseEvent) => {
|
||||
// Calculate the new element coordinates.
|
||||
|
@ -747,3 +745,274 @@ export function addResizementListener(
|
|||
handleEnd();
|
||||
};
|
||||
}
|
||||
|
||||
// TODO: Document and code
|
||||
export function t(text: string): string {
|
||||
return text;
|
||||
}
|
||||
|
||||
export function helpTip(text: string): HTMLElement {
|
||||
const container = document.createElement("a");
|
||||
container.className = "tip";
|
||||
const icon = document.createElement("img");
|
||||
icon.src = helpTipIcon;
|
||||
icon.className = "forced_title";
|
||||
icon.setAttribute("alt", text);
|
||||
icon.setAttribute("data-title", text);
|
||||
icon.setAttribute("data-use_title_for_force_title", "1");
|
||||
|
||||
container.appendChild(icon);
|
||||
|
||||
return container;
|
||||
}
|
||||
|
||||
interface PeriodSelectorOption {
|
||||
value: number;
|
||||
text: string;
|
||||
}
|
||||
export function periodSelector(
|
||||
selectedValue: PeriodSelectorOption["value"] | null,
|
||||
emptyOption: PeriodSelectorOption | null,
|
||||
options: PeriodSelectorOption[],
|
||||
onChange: (value: PeriodSelectorOption["value"]) => void
|
||||
): HTMLElement {
|
||||
if (selectedValue === null) selectedValue = 0;
|
||||
const initialValue = emptyOption ? emptyOption.value : 0;
|
||||
let currentValue: number =
|
||||
selectedValue != null ? selectedValue : initialValue;
|
||||
// Main container.
|
||||
const container = document.createElement("div");
|
||||
// Container for the period selector.
|
||||
const periodsContainer = document.createElement("div");
|
||||
const selectPeriods = document.createElement("select");
|
||||
const useManualPeriodsBtn = document.createElement("a");
|
||||
// Container for the custom period input.
|
||||
const manualPeriodsContainer = document.createElement("div");
|
||||
const inputTimeValue = document.createElement("input");
|
||||
const unitsSelect = document.createElement("select");
|
||||
const usePeriodsBtn = document.createElement("a");
|
||||
// Units to multiply the custom period input.
|
||||
const unitOptions: { value: string; text: string }[] = [
|
||||
{ value: "1", text: t("Seconds").toLowerCase() },
|
||||
{ value: "60", text: t("Minutes").toLowerCase() },
|
||||
{ value: "3600", text: t("Hours").toLowerCase() },
|
||||
{ value: "86400", text: t("Days").toLowerCase() },
|
||||
{ value: "604800", text: t("Weeks").toLowerCase() },
|
||||
{ value: `${86400 * 30}`, text: t("Months").toLowerCase() },
|
||||
{ value: `${86400 * 30 * 12}`, text: t("Years").toLowerCase() }
|
||||
];
|
||||
|
||||
// Will be executed every time the value changes.
|
||||
const handleChange = (value: number) => {
|
||||
currentValue = value;
|
||||
onChange(currentValue);
|
||||
};
|
||||
// Will return the first period option smaller than the value.
|
||||
const findPeriodsOption = (value: number) =>
|
||||
options
|
||||
.sort((a, b) => (a.value < b.value ? 1 : -1))
|
||||
.find(optionVal => value >= optionVal.value);
|
||||
// Will return the first multiple of the value using the custom input multipliers.
|
||||
const findManualPeriodsOptionValue = (value: number) =>
|
||||
unitOptions
|
||||
.map(unitOption => Number.parseInt(unitOption.value))
|
||||
.sort((a, b) => (a < b ? 1 : -1))
|
||||
.find(optionVal => value % optionVal === 0);
|
||||
// Will find and set a valid option for the period selector.
|
||||
const setPeriodsValue = (value: number) => {
|
||||
let option = findPeriodsOption(value);
|
||||
selectPeriods.value = `${option ? option.value : initialValue}`;
|
||||
};
|
||||
// Will transform the value to show the perfect fit for the custom input period.
|
||||
const setManualPeriodsValue = (value: number) => {
|
||||
const optionVal = findManualPeriodsOptionValue(value);
|
||||
if (optionVal) {
|
||||
inputTimeValue.value = `${value / optionVal}`;
|
||||
unitsSelect.value = `${optionVal}`;
|
||||
} else {
|
||||
inputTimeValue.value = `${value}`;
|
||||
unitsSelect.value = "1";
|
||||
}
|
||||
};
|
||||
|
||||
// Will modify the value to show the perfect fit for this element and show its container.
|
||||
const showPeriods = () => {
|
||||
let option = findPeriodsOption(currentValue);
|
||||
const newValue = option ? option.value : initialValue;
|
||||
selectPeriods.value = `${newValue}`;
|
||||
|
||||
if (newValue !== currentValue) handleChange(newValue);
|
||||
|
||||
container.replaceChild(periodsContainer, manualPeriodsContainer);
|
||||
};
|
||||
// Will modify the value to show the perfect fit for this element and show its container.
|
||||
const showManualPeriods = () => {
|
||||
const optionVal = findManualPeriodsOptionValue(currentValue);
|
||||
|
||||
if (optionVal) {
|
||||
inputTimeValue.value = `${currentValue / optionVal}`;
|
||||
unitsSelect.value = `${optionVal}`;
|
||||
} else {
|
||||
inputTimeValue.value = `${currentValue}`;
|
||||
unitsSelect.value = "1";
|
||||
}
|
||||
|
||||
container.replaceChild(manualPeriodsContainer, periodsContainer);
|
||||
};
|
||||
|
||||
// Append the elements
|
||||
|
||||
periodsContainer.appendChild(selectPeriods);
|
||||
periodsContainer.appendChild(useManualPeriodsBtn);
|
||||
|
||||
manualPeriodsContainer.appendChild(inputTimeValue);
|
||||
manualPeriodsContainer.appendChild(unitsSelect);
|
||||
manualPeriodsContainer.appendChild(usePeriodsBtn);
|
||||
|
||||
if (
|
||||
options.find(option => option.value === selectedValue) ||
|
||||
(emptyOption && emptyOption.value === selectedValue)
|
||||
) {
|
||||
// Start with the custom periods select.
|
||||
container.appendChild(periodsContainer);
|
||||
} else {
|
||||
// Start with the manual time input
|
||||
container.appendChild(manualPeriodsContainer);
|
||||
}
|
||||
|
||||
// Set and fill the elements.
|
||||
|
||||
// Periods selector.
|
||||
|
||||
selectPeriods.addEventListener("change", (e: Event) =>
|
||||
handleChange(
|
||||
parseIntOr((e.target as HTMLSelectElement).value, initialValue)
|
||||
)
|
||||
);
|
||||
if (emptyOption) {
|
||||
const optionElem = document.createElement("option");
|
||||
optionElem.value = `${emptyOption.value}`;
|
||||
optionElem.text = emptyOption.text;
|
||||
selectPeriods.appendChild(optionElem);
|
||||
}
|
||||
options.forEach(option => {
|
||||
const optionElem = document.createElement("option");
|
||||
optionElem.value = `${option.value}`;
|
||||
optionElem.text = option.text;
|
||||
selectPeriods.appendChild(optionElem);
|
||||
});
|
||||
|
||||
setPeriodsValue(selectedValue);
|
||||
|
||||
useManualPeriodsBtn.appendChild(
|
||||
fontAwesomeIcon(faPencilAlt, t("Show manual period input"), {
|
||||
size: "small"
|
||||
})
|
||||
);
|
||||
useManualPeriodsBtn.addEventListener("click", e => {
|
||||
e.preventDefault();
|
||||
showManualPeriods();
|
||||
});
|
||||
|
||||
// Manual periods input.
|
||||
|
||||
inputTimeValue.type = "number";
|
||||
inputTimeValue.min = "0";
|
||||
inputTimeValue.required = true;
|
||||
inputTimeValue.addEventListener("change", (e: Event) =>
|
||||
handleChange(
|
||||
parseIntOr((e.target as HTMLSelectElement).value, 0) *
|
||||
parseIntOr(unitsSelect.value, 1)
|
||||
)
|
||||
);
|
||||
// Select for time units.
|
||||
unitsSelect.addEventListener("change", (e: Event) =>
|
||||
handleChange(
|
||||
parseIntOr(inputTimeValue.value, 0) *
|
||||
parseIntOr((e.target as HTMLSelectElement).value, 1)
|
||||
)
|
||||
);
|
||||
unitOptions.forEach(option => {
|
||||
const optionElem = document.createElement("option");
|
||||
optionElem.value = `${option.value}`;
|
||||
optionElem.text = option.text;
|
||||
unitsSelect.appendChild(optionElem);
|
||||
});
|
||||
|
||||
setManualPeriodsValue(selectedValue);
|
||||
|
||||
usePeriodsBtn.appendChild(
|
||||
fontAwesomeIcon(faListAlt, t("Show periods selector"), { size: "small" })
|
||||
);
|
||||
usePeriodsBtn.addEventListener("click", e => {
|
||||
e.preventDefault();
|
||||
showPeriods();
|
||||
});
|
||||
|
||||
return container;
|
||||
}
|
||||
|
||||
/**
|
||||
* Cuts the text if their length is greater than the selected max length
|
||||
* and applies the selected ellipse to the result text.
|
||||
* @param str Text to cut
|
||||
* @param max Maximum length after cutting the text
|
||||
* @param ellipse String to be added to the cutted text
|
||||
* @returns Full text or text cutted with the ellipse
|
||||
*/
|
||||
export function ellipsize(
|
||||
str: string,
|
||||
max: number = 140,
|
||||
ellipse: string = "…"
|
||||
): string {
|
||||
return str.trim().length > max ? str.substr(0, max).trim() + ellipse : str;
|
||||
}
|
||||
|
||||
// TODO: Document
|
||||
export function autocompleteInput<T>(
|
||||
initialValue: string | null,
|
||||
onDataRequested: (value: string, done: (data: T[]) => void) => void,
|
||||
renderListElement: (data: T) => HTMLElement,
|
||||
onSelected: (data: T) => string
|
||||
): HTMLElement {
|
||||
const container = document.createElement("div");
|
||||
container.classList.add("autocomplete");
|
||||
|
||||
const input = document.createElement("input");
|
||||
input.type = "text";
|
||||
input.required = true;
|
||||
if (initialValue !== null) input.value = initialValue;
|
||||
|
||||
const list = document.createElement("div");
|
||||
list.classList.add("autocomplete-items");
|
||||
|
||||
const cleanList = () => {
|
||||
list.innerHTML = "";
|
||||
};
|
||||
|
||||
input.addEventListener("keyup", e => {
|
||||
const value = (e.target as HTMLInputElement).value;
|
||||
if (value) {
|
||||
onDataRequested(value, data => {
|
||||
cleanList();
|
||||
if (data instanceof Array) {
|
||||
data.forEach(item => {
|
||||
const listElement = renderListElement(item);
|
||||
listElement.addEventListener("click", () => {
|
||||
input.value = onSelected(item);
|
||||
cleanList();
|
||||
});
|
||||
list.appendChild(listElement);
|
||||
});
|
||||
}
|
||||
});
|
||||
} else {
|
||||
cleanList();
|
||||
}
|
||||
});
|
||||
|
||||
container.appendChild(input);
|
||||
container.appendChild(list);
|
||||
|
||||
return container;
|
||||
}
|
||||
|
|
|
@ -132,7 +132,11 @@ describe("itemMetaDecoder function", () => {
|
|||
isFromCache: false,
|
||||
isFetching: false,
|
||||
isUpdating: false,
|
||||
editMode: false
|
||||
editMode: false,
|
||||
isBeingMoved: false,
|
||||
isBeingResized: false,
|
||||
isSelected: false,
|
||||
lineMode: false
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -149,7 +153,11 @@ describe("itemMetaDecoder function", () => {
|
|||
isFromCache: false,
|
||||
isFetching: false,
|
||||
isUpdating: false,
|
||||
editMode: true
|
||||
editMode: true,
|
||||
isBeingMoved: false,
|
||||
isBeingResized: false,
|
||||
isSelected: false,
|
||||
lineMode: false
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
@ -45,9 +45,8 @@ export type LinkedVisualConsolePropsStatus =
|
|||
linkedLayoutStatusTypeCriticalThreshold: number;
|
||||
};
|
||||
export type LinkedVisualConsoleProps = {
|
||||
metaconsoleId?: number | null;
|
||||
linkedLayoutId: number | null;
|
||||
linkedLayoutAgentId: number | null;
|
||||
linkedLayoutNodeId: number | null;
|
||||
} & LinkedVisualConsolePropsStatus;
|
||||
|
||||
export interface ItemMeta {
|
||||
|
@ -56,5 +55,9 @@ export interface ItemMeta {
|
|||
isFromCache: boolean;
|
||||
isFetching: boolean;
|
||||
isUpdating: boolean;
|
||||
isSelected: boolean;
|
||||
isBeingMoved: boolean;
|
||||
isBeingResized: boolean;
|
||||
editMode: boolean;
|
||||
lineMode: boolean;
|
||||
}
|
||||
|
|
|
@ -13,15 +13,23 @@
|
|||
justify-items: center;
|
||||
align-items: center;
|
||||
user-select: text;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.visual-console-item.is-on-top {
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.visual-console-item.is-editing {
|
||||
border: 2px dashed #b2b2b2;
|
||||
transform: translateX(-2px) translateY(-2px);
|
||||
cursor: move;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.visual-console-item.is-editing.is-selected {
|
||||
border: 2px dashed #2b2b2b;
|
||||
cursor: move;
|
||||
}
|
||||
.visual-console-item.is-editing > .resize-draggable {
|
||||
float: right;
|
||||
position: absolute;
|
||||
|
@ -32,3 +40,493 @@
|
|||
background: url(./resize-handle.svg);
|
||||
cursor: se-resize;
|
||||
}
|
||||
|
||||
.visual-console-item.is-editing :first-child {
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
@keyframes spinner-loading {
|
||||
0% {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
to {
|
||||
transform: rotate(1turn);
|
||||
}
|
||||
}
|
||||
|
||||
.visual-console-spinner {
|
||||
background-color: transparent;
|
||||
margin: 0px auto;
|
||||
border-top: 5px solid rgb(82, 85, 87);
|
||||
border-right: 5px solid rgb(82, 85, 87);
|
||||
border-bottom: 5px solid rgb(82, 85, 87);
|
||||
border-left: 5px solid rgba(82, 85, 87, 0.2);
|
||||
|
||||
animation-name: spinner-loading;
|
||||
animation-duration: 0.8s;
|
||||
animation-iteration-count: infinite;
|
||||
animation-timing-function: linear;
|
||||
}
|
||||
|
||||
.visual-console-spinner,
|
||||
.visual-console-spinner :after {
|
||||
display: block;
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.visual-console-spinner.small,
|
||||
.visual-console-spinner.small :after {
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
}
|
||||
|
||||
.div-visual-console-spinner {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
opacity: 0.7;
|
||||
background: rgb(212, 215, 218);
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.show-elements {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.hide-elements {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/*Forms*/
|
||||
.div-input-group label {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
font-size: 12pt;
|
||||
font-family: "lato-bolder", "Open Sans", sans-serif;
|
||||
font-weight: 600;
|
||||
color: #343434;
|
||||
margin-right: 10px;
|
||||
}
|
||||
.div-input-group label img {
|
||||
margin-left: 4px;
|
||||
}
|
||||
|
||||
.div-input-group input[type="text"],
|
||||
.div-input-group input[type="number"] {
|
||||
height: 25px;
|
||||
font-size: 10pt;
|
||||
background-color: transparent;
|
||||
border: none;
|
||||
border-radius: 0;
|
||||
border-bottom: 1px solid #ccc;
|
||||
font-family: "lato-bolder", "Open Sans", sans-serif;
|
||||
font-weight: lighter;
|
||||
padding: 0px 0px 2px 0px;
|
||||
box-sizing: border-box;
|
||||
margin-right: 10px;
|
||||
padding-left: 2px;
|
||||
}
|
||||
|
||||
.div-input-group input[type="radio"] {
|
||||
margin-right: 10px;
|
||||
width: 17px;
|
||||
height: 17px;
|
||||
}
|
||||
|
||||
.div-input-group select {
|
||||
font-family: "lato-bolder", "Open Sans", sans-serif;
|
||||
font-weight: lighter;
|
||||
font-size: 10pt;
|
||||
}
|
||||
|
||||
.input-groups {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.input-group {
|
||||
width: 100%;
|
||||
margin-bottom: 25px;
|
||||
padding-left: 20px;
|
||||
}
|
||||
|
||||
.div-ranges-input-group {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex-wrap: wrap;
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
.div-ranges-input-group > div {
|
||||
padding-left: 20px;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.div-input-group,
|
||||
.div-input-group div div {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.div-input-group h3 {
|
||||
text-transform: initial;
|
||||
font-family: "lato-bolder", "Open Sans", sans-serif;
|
||||
text-align: center;
|
||||
font-style: italic;
|
||||
text-decoration: underline;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.div-input-group div div a {
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
.div-input-group-autocomplete-agent {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex-wrap: wrap;
|
||||
align-items: flex-start;
|
||||
justify-content: space-between;
|
||||
height: 70px;
|
||||
}
|
||||
|
||||
.div-input-group-inside {
|
||||
padding-left: 20px;
|
||||
}
|
||||
|
||||
.input-group-link-console {
|
||||
height: 70px;
|
||||
}
|
||||
|
||||
.show-elements > div.div-input-group-autocomplete-agent {
|
||||
margin-left: 20px;
|
||||
}
|
||||
|
||||
.img-vc-elements {
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
input.error-input-validate[type="number"],
|
||||
input.error-input-validate[type="text"],
|
||||
select.error-input-validate {
|
||||
border: 1px solid #c00;
|
||||
}
|
||||
|
||||
select.error-input-validate:focus {
|
||||
outline-color: #c00;
|
||||
}
|
||||
|
||||
p.error-p-validate {
|
||||
width: 100%;
|
||||
color: #c00;
|
||||
}
|
||||
|
||||
/* Styles for the solid icons */
|
||||
|
||||
.fa {
|
||||
display: inline-block;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.fa,
|
||||
.fa > svg,
|
||||
.fa.medium,
|
||||
.fa.medium > svg {
|
||||
width: 28px;
|
||||
height: 28px;
|
||||
}
|
||||
|
||||
.fa.fa-small,
|
||||
.fa.fa-small > svg {
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
}
|
||||
|
||||
.fa.fa-large,
|
||||
.fa.fa-large > svg {
|
||||
width: 44px;
|
||||
height: 44px;
|
||||
}
|
||||
|
||||
.fa-spin {
|
||||
animation: fa-spin 2s infinite linear;
|
||||
}
|
||||
|
||||
.fa-pulse {
|
||||
animation: fa-spin 1s infinite steps(8);
|
||||
}
|
||||
|
||||
@keyframes fa-spin {
|
||||
0% {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
100% {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
|
||||
.autocomplete {
|
||||
/*the container must be positioned relative:*/
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
}
|
||||
.autocomplete input {
|
||||
/*background: pink;*/
|
||||
}
|
||||
.autocomplete-items {
|
||||
border: 1px solid #d4d4d4;
|
||||
border-bottom: none;
|
||||
border-top: none;
|
||||
/*position the autocomplete items to be the same width as the container:*/
|
||||
position: absolute;
|
||||
z-index: 1;
|
||||
overflow: auto;
|
||||
max-height: 150px;
|
||||
max-width: 250px;
|
||||
}
|
||||
.autocomplete-items div {
|
||||
width: 100%;
|
||||
padding: 10px;
|
||||
cursor: pointer;
|
||||
background-color: #fff;
|
||||
border-bottom: 1px solid #d4d4d4;
|
||||
border-top: 1px solid #d4d4d4;
|
||||
}
|
||||
.autocomplete-items div:hover {
|
||||
width: 100%;
|
||||
background-color: #e9e9e9;
|
||||
}
|
||||
.autocomplete-active {
|
||||
/*when navigating through the items using the arrow keys:*/
|
||||
background-color: DodgerBlue !important;
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
/*
|
||||
@font-face {
|
||||
font-family: Alarm Clock;
|
||||
src: url(alarm-clock.ttf);
|
||||
}
|
||||
*/
|
||||
|
||||
/* Digital clock */
|
||||
|
||||
.visual-console-item .digital-clock {
|
||||
display: -webkit-box;
|
||||
display: -ms-flexbox;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
justify-items: center;
|
||||
align-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.visual-console-item .digital-clock > span {
|
||||
/* To improve legibility */
|
||||
text-rendering: optimizeLegibility;
|
||||
text-shadow: rgba(0, 0, 0, 0.01) 0 0 1px;
|
||||
}
|
||||
|
||||
.visual-console-item .digital-clock > span.time {
|
||||
font-family: "Alarm Clock", "Courier New", Courier, monospace;
|
||||
font-size: 50px;
|
||||
}
|
||||
|
||||
.visual-console-item .digital-clock > span.date {
|
||||
font-family: "Alarm Clock", "Courier New", Courier, monospace;
|
||||
font-size: 25px;
|
||||
}
|
||||
|
||||
.visual-console-item .digital-clock > span.timezone {
|
||||
font-size: 25px;
|
||||
}
|
||||
|
||||
/* Analog clock */
|
||||
|
||||
.visual-console-item .analogic-clock {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.visual-console-item .analogic-clock .hour-hand {
|
||||
animation: rotate-hour 43200s infinite linear;
|
||||
}
|
||||
|
||||
.visual-console-item .analogic-clock .minute-hand {
|
||||
animation: rotate-minute 3600s infinite linear;
|
||||
}
|
||||
|
||||
.visual-console-item .analogic-clock .second-hand {
|
||||
animation: rotate-second 60s infinite linear;
|
||||
}
|
||||
|
||||
#html-tabs .ui-widget-header {
|
||||
background-color: #ffffff;
|
||||
border: 0px;
|
||||
}
|
||||
|
||||
#html-tabs .ui-tabs-anchor {
|
||||
float: none;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
#html-tabs .ui-tabs-anchor img {
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
#html-tabs .ui-tabs-nav li {
|
||||
border-radius: 5px 5px 0px 0px;
|
||||
}
|
||||
|
||||
label span.p-slider {
|
||||
width: 30px;
|
||||
}
|
||||
|
||||
li.interval-color-ranges > label,
|
||||
li#li-default-ranges > label {
|
||||
margin-right: 15px;
|
||||
}
|
||||
|
||||
li.interval-color-ranges > input[type="number"],
|
||||
li#li-default-ranges > input[type="number"] {
|
||||
width: 80px;
|
||||
}
|
||||
|
||||
li.interval-color-ranges > label:not(:first-child),
|
||||
li#li-default-ranges > label:not(:first-child),
|
||||
li#li-size-item > label:not(:first-child),
|
||||
li#li-position-item > label:not(:first-child) {
|
||||
width: initial;
|
||||
margin-left: 15px;
|
||||
}
|
||||
|
||||
li#li-image-item label {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
li#li-image-item label img {
|
||||
flex: initial;
|
||||
}
|
||||
|
||||
.discovery.modal * {
|
||||
font-weight: normal;
|
||||
color: #343434;
|
||||
font-family: "lato", "Open Sans", sans-serif;
|
||||
}
|
||||
|
||||
.discovery.modal select {
|
||||
width: 100px;
|
||||
}
|
||||
|
||||
.discovery.modal div#period_manual select,
|
||||
.discovery.modal div#period_manual input,
|
||||
.discovery.modal div#period_default select,
|
||||
.discovery.modal div#cacheExpiration_manual select,
|
||||
.discovery.modal div#cacheExpiration_manual input,
|
||||
.discovery.modal div#cacheExpiration_default select {
|
||||
font-size: inherit !important;
|
||||
}
|
||||
.discovery.modal div#period_default select#period_select,
|
||||
.discovery.modal div#cacheExpiration_default select#cacheExpiration_select {
|
||||
max-width: 230px;
|
||||
width: inherit;
|
||||
}
|
||||
|
||||
li#li-timeZone-item > label:not(:first-child),
|
||||
.discovery.modal li#div-textarea-label > label {
|
||||
flex: inherit;
|
||||
}
|
||||
|
||||
li#li-timeZone-item > select:not(:first-child) {
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
.discovery.modal li#div-textarea-label table tbody td.mceIframeContainer {
|
||||
background-color: #ededed;
|
||||
}
|
||||
|
||||
/*style item group show statistic*/
|
||||
.group-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
.group-container .group-item-title {
|
||||
width: 100%;
|
||||
height: 30%;
|
||||
background-color: #9d9ea0;
|
||||
color: black;
|
||||
font-weight: bold;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
.group-container .group-item-info {
|
||||
width: 100%;
|
||||
height: 70%;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
padding: 2%;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.group-container .group-item-info .group-item-info-container {
|
||||
flex: 1 1 80px;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
border-radius: 2px;
|
||||
height: 100%;
|
||||
max-height: 50px;
|
||||
margin: 5px;
|
||||
}
|
||||
|
||||
.group-container .group-item-info .group-item-info-container .value-style {
|
||||
flex: 1;
|
||||
color: #fff;
|
||||
font-size: 100%;
|
||||
padding: 5px;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.group-container .group-item-info .group-item-info-container .name-style {
|
||||
flex: 1;
|
||||
background-color: white;
|
||||
color: black;
|
||||
font-size: 100%;
|
||||
padding: 5px;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
div.label,
|
||||
div.simple-value {
|
||||
display: inline-table;
|
||||
min-width: fit-content;
|
||||
min-height: fit-content;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue