Visual Console Refactor: added the initial version of the background updates

Former-commit-id: 6c859ebebf4882b3e48e9ec5f99570687ec31117
This commit is contained in:
Alejandro Gallardo Escobar 2019-04-11 10:05:28 +02:00
parent c8e0fad8ca
commit 3928a5a523
4 changed files with 378 additions and 68 deletions

View File

@ -1,3 +1,267 @@
// TODO: Add Artica ST header.
/* globals jQuery, VisualConsole */
/*
* *********************
* * New VC functions. *
* *********************
*/
/**
* Generate a Visual Console client.
* @param {HTMLElement} container Node which will be used to contain the VC.
* @param {object} props VC container properties.
* @param {object[]} items List of item definitions.
* @param {string | null} baseUrl Base URL to perform API requests.
* @param {number | null} updateInterval Time in milliseconds between VC updates.
* @param {function | null} onUpdate Callback which will be execuded when the Visual Console.
* is updated. It will receive two arguments with the old and the new Visual Console's
* data structure.
* @return {VisualConsole | null} The Visual Console instance or a null value.
*/
// eslint-disable-next-line no-unused-vars
function createVisualConsole(
container,
props,
items,
baseUrl,
updateInterval,
onUpdate
) {
var visualConsole = null;
var linkedVCRequest = null;
var updateVCRequest = null;
if (container == null || props == null || items == null) return null;
if (baseUrl == null) baseUrl = "";
if (updateInterval == null) updateInterval = 30000;
// Code which will be executed between intervals.
var intervalRef = null;
var stopInterval = function() {
if (intervalRef !== null) window.clearInterval(intervalRef);
};
var startInterval = function() {
stopInterval();
intervalRef = window.setInterval(function() {
if (updateVCRequest !== null) updateVCRequest.abort();
updateVCRequest = loadVisualConsoleData(
baseUrl,
visualConsole.props.id,
function(error, data) {
if (error) {
console.log(
"[ERROR]",
"[VISUAL-CONSOLE-CLIENT]",
"[API]",
error.message
);
return;
}
// Replace Visual Console.
if (data != null && data.props != null && data.items != null) {
try {
var props =
typeof data.props === "string"
? JSON.parse(data.props)
: data.props;
var items =
typeof data.items === "string"
? JSON.parse(data.items)
: data.items;
var prevProps = visualConsole.props;
// Update the data structure.
visualConsole.props = props;
// Update the items.
visualConsole.updateElements(items);
// Emit the VC update event.
if (onUpdate) onUpdate(prevProps, visualConsole.props);
} catch (ignored) {} // eslint-disable-line no-empty
}
}
);
}, updateInterval);
};
// Initialize the Visual Console.
try {
visualConsole = new VisualConsole(container, props, items);
// VC Item clicked.
visualConsole.onClick(function(e) {
// Override the link to another VC if it isn't on remote console.
if (
e.data &&
e.data.linkedLayoutId != null &&
e.data.linkedLayoutId > 0 &&
e.data.link != null &&
e.data.link.length > 0 &&
(e.data.metaconsoleId == null || e.data.metaconsoleId === 0)
) {
// Stop the current link behavior.
e.nativeEvent.preventDefault();
// Fetch and update the old VC with the new.
if (linkedVCRequest !== null) linkedVCRequest.abort();
linkedVCRequest = loadVisualConsoleData(
baseUrl,
e.data.linkedLayoutId,
function(error, data) {
if (error) {
console.log(
"[ERROR]",
"[VISUAL-CONSOLE-CLIENT]",
"[API]",
error.message
);
return;
}
// Replace Visual Console.
if (data != null && data.props != null && data.items != null) {
// Cancel the old VC updates.
stopInterval();
try {
var props =
typeof data.props === "string"
? JSON.parse(data.props)
: data.props;
var items =
typeof data.items === "string"
? JSON.parse(data.items)
: data.items;
if (updateVCRequest !== null) updateVCRequest.abort();
// Save the old props.
var prevProps = visualConsole.props;
// Update the data structure.
visualConsole.props = props;
// Update the items.
visualConsole.updateElements(items);
// Emit the VC update event.
if (onUpdate) onUpdate(prevProps, visualConsole.props);
} catch (ignored) {} // eslint-disable-line no-empty
// Restart the updates.
startInterval();
}
}
);
}
});
// Start an interval to update the Visual Console.
startInterval();
} catch (error) {
console.log("[ERROR]", "[VISUAL-CONSOLE-CLIENT]", error.message);
}
return visualConsole;
}
/**
* Fetch a Visual Console's structure and its items.
* @param {string} baseUrl Base URL to build the API path.
* @param {number} vcId Identifier of the Visual Console.
* @param {function} callback Function to be executed on request success or fail.
* On success, the function will receive an object with the next properties:
* - `props`: object with the Visual Console's data structure.
* - `items`: array of data structures of the Visual Console's items.
* @return {Object} Cancellable. Object which include and .abort([statusText]) function.
*/
// eslint-disable-next-line no-unused-vars
function loadVisualConsoleData(baseUrl, vcId, callback) {
// var apiPath = baseUrl + "/include/rest-api";
var apiPath = baseUrl + "/ajax.php";
var vcJqXHR = null;
var itemsJqXHR = null;
// Initialize the final result.
var result = {
props: null,
items: null
};
// Cancel the ajax requests.
var abort = function(textStatus) {
if (textStatus == null) textStatus = "abort";
// -- XMLHttpRequest.readyState --
// Value State Description
// 0 UNSENT Client has been created. open() not called yet.
// 4 DONE The operation is complete.
if (vcJqXHR.readyState !== 0 && vcJqXHR.readyState !== 4)
vcJqXHR.abort(textStatus);
if (itemsJqXHR.readyState !== 0 && itemsJqXHR.readyState !== 4)
itemsJqXHR.abort(textStatus);
};
// Check if the required data is complete.
var checkResult = function() {
return result.props !== null && result.items !== null;
};
// Failed request handler.
var handleFail = function(jqXHR, textStatus, errorThrown) {
abort();
// Manually aborted or not.
if (textStatus === "abort") {
callback();
} else {
var error = new Error(errorThrown);
error.request = jqXHR;
callback(error);
}
};
// Curried function which handle success.
var handleSuccess = function(key) {
// Actual request handler.
return function(data) {
result[key] = data;
if (checkResult()) callback(null, result);
};
};
// Visual Console container request.
vcJqXHR = jQuery
// .get(apiPath + "/visual-consoles/" + vcId, null, "json")
.get(
apiPath,
{
page: "include/rest-api/index",
getVisualConsole: 1,
visualConsoleId: vcId
},
"json"
)
.done(handleSuccess("props"))
.fail(handleFail);
// Visual Console items request.
itemsJqXHR = jQuery
// .get(apiPath + "/visual-consoles/" + vcId + "/items", null, "json")
.get(
apiPath,
{
page: "include/rest-api/index",
getVisualConsoleItems: 1,
visualConsoleId: vcId
},
"json"
)
.done(handleSuccess("items"))
.fail(handleFail);
// Abortable.
return {
abort: abort
};
}
// TODO: Delete the functions below when you can.
/**************************************
These functions require jQuery library
**************************************/

View File

@ -0,0 +1,25 @@
<?php
if (!is_ajax()) {
return;
}
global $config;
require_once $config['homedir'].'/vendor/autoload.php';
use Models\VisualConsole\Container as VisualConsole;
$visualConsoleId = (int) get_parameter('visualConsoleId');
$getVisualConsole = (bool) get_parameter('getVisualConsole');
$getVisualConsoleItems = (bool) get_parameter('getVisualConsoleItems');
ob_clean();
if ($getVisualConsole === true) {
echo VisualConsole::fromDB(['id' => $visualConsoleId]);
} else if ($getVisualConsoleItems === true) {
echo '['.implode(VisualConsole::getItemsFromDB($visualConsoleId), ',').']';
}
exit;

View File

@ -34,6 +34,8 @@ echo '<head>';
global $vc_public_view;
$vc_public_view = true;
$config['public_view'] = true;
// This starts the page head. In the call back function,
// things from $page['head'] array will be processed into the head.
ob_start('ui_process_page_head');
@ -42,72 +44,72 @@ enterprise_include('index.php');
require_once 'include/functions_visual_map.php';
$hash = get_parameter('hash');
$id_layout = (int) get_parameter('id_layout');
$graph_javascript = (bool) get_parameter('graph_javascript');
$config['id_user'] = get_parameter('id_user');
$hash = (string) get_parameter('hash');
$visualConsoleId = (int) get_parameter('id_layout');
$config['id_user'] = (string) get_parameter('id_user');
$refr = (int) get_parameter('refr', 0);
$layout = db_get_row('tlayout', 'id', $visualConsoleId);
$myhash = md5($config['dbpass'].$id_layout.$config['id_user']);
if (!isset($config['pure'])) {
$config['pure'] = 0;
}
$myhash = md5($config['dbpass'].$visualConsoleId.$config['id_user']);
// Check input hash.
if ($myhash != $hash) {
exit;
}
$refr = (int) get_parameter('refr', 0);
$layout = db_get_row('tlayout', 'id', $id_layout);
if (! $layout) {
db_pandora_audit('ACL Violation', 'Trying to access visual console without id layout');
if (!$layout) {
db_pandora_audit(
'ACL Violation',
'Trying to access visual console without id layout'
);
include $config['homedir'].'/general/noaccess.php';
exit;
}
if (!isset($config['pure'])) {
$config['pure'] = 0;
}
use Models\VisualConsole\Container as VisualConsole;
if ($layout) {
$id_group = $layout['id_group'];
$layout_name = $layout['name'];
$visualConsoleName = $layout['name'];
$visualConsole = VisualConsole::fromArray($layout);
$visualConsoleItems = VisualConsole::getItemsFromDB($id_layout);
// TODO: Show an error message when the models can't be loaded.
$visualConsole = VisualConsole::fromArray($layout);
$visualConsoleItems = VisualConsole::getItemsFromDB($visualConsoleId);
// TODO: Extract to a function.
$vcClientPath = 'include/visual-console-client';
$dir = $config['homedir'].'/'.$vcClientPath;
if (is_dir($dir)) {
$dh = opendir($dir);
if ($dh) {
while (($file = readdir($dh)) !== false) {
if ($file === '.' || $file === '..') {
continue;
}
preg_match('/.*.js$/', $file, $match, PREG_OFFSET_CAPTURE);
if (empty($match) === false) {
$url = ui_get_full_url(false, false, false, false).$vcClientPath.'/'.$match[0][0];
echo '<script type="text/javascript" src="'.$url.'"></script>';
continue;
}
preg_match('/.*.css$/', $file, $match, PREG_OFFSET_CAPTURE);
if (empty($match) === false) {
$url = ui_get_full_url(false, false, false, false).$vcClientPath.'/'.$match[0][0];
echo '<link rel="stylesheet" type="text/css" href="'.$url.'" />';
}
// TODO: Extract to a function.
$baseUrl = ui_get_full_url(false, false, false, false);
$vcClientPath = 'include/visual-console-client';
$dir = $config['homedir'].'/'.$vcClientPath;
if (is_dir($dir)) {
$dh = opendir($dir);
if ($dh) {
while (($file = readdir($dh)) !== false) {
if ($file === '.' || $file === '..') {
continue;
}
closedir($dh);
}
}
preg_match('/.*.js$/', $file, $match, PREG_OFFSET_CAPTURE);
if (empty($match) === false) {
$url = $baseUrl.$vcClientPath.'/'.$match[0][0];
echo '<script type="text/javascript" src="'.$url.'"></script>';
continue;
}
echo '<div id="visual-console-container" style="margin:0px auto;position:relative;"></div>';
preg_match('/.*.css$/', $file, $match, PREG_OFFSET_CAPTURE);
if (empty($match) === false) {
$url = $baseUrl.$vcClientPath.'/'.$match[0][0];
echo '<link type="text/css" rel="stylesheet" href="'.$url.'" />';
}
}
closedir($dh);
}
}
echo '<div id="visual-console-container" style="margin:0px auto;position:relative;"></div>';
// Floating menu - Start.
echo '<div id="vc-controls" style="z-index:300;">';
@ -123,32 +125,40 @@ echo '</li>';
// Console name.
echo '<li class="nomn">';
echo '<div class="vc-title">'.$layout_name.'</div>';
echo '<div class="vc-title">'.$visualConsoleName.'</div>';
echo '</li>';
echo '</ul>';
echo '</div>';
echo '</div>';
// Floating menu - End
// QR code dialog.
echo '<div style="display: none;" id="qrcode_container" title="'.__('QR code of the page').'">';
echo '<div id="qrcode_container_image"></div>';
echo '</div>';
$ignored_params['refr'] = '';
ui_require_javascript_file('pandora_visual_console');
?>
<script type="text/javascript">
var container = document.getElementById("visual-console-container");
var props = <?php echo (string) $visualConsole; ?>;
var items = <?php echo '['.implode($visualConsoleItems, ',').']'; ?>;
if (container != null) {
try {
var visualConsole = new VisualConsole(container, props, items);
console.log(visualConsole);
} catch (error) {
console.log("ERROR", error.message);
}
var baseUrl = "<?php echo $config['homeurl']; ?>";
var handleUpdate = function (prevProps, newProps) {
// TODO: Change the view header and links to display id or name changes.
}
var visualConsole = createVisualConsole(
container,
props,
items,
baseUrl,
10000,
handleUpdate
);
$(document).ready(function () {
var controls = document.getElementById('vc-controls');
if (controls) autoHideElement(controls, 1000);
});
</script>

View File

@ -143,6 +143,7 @@ $visualConsole = VisualConsole::fromArray($layout);
$visualConsoleItems = VisualConsole::getItemsFromDB($visualConsoleId);
// TODO: Extract to a function.
$baseUrl = ui_get_full_url(false, false, false, false);
$vcClientPath = 'include/visual-console-client';
$dir = $config['homedir'].'/'.$vcClientPath;
if (is_dir($dir)) {
@ -155,15 +156,15 @@ if (is_dir($dir)) {
preg_match('/.*.js$/', $file, $match, PREG_OFFSET_CAPTURE);
if (empty($match) === false) {
$url = ui_get_full_url(false, false, false, false).$vcClientPath.'/'.$match[0][0];
$url = $baseUrl.$vcClientPath.'/'.$match[0][0];
echo '<script type="text/javascript" src="'.$url.'"></script>';
continue;
}
preg_match('/.*.css$/', $file, $match, PREG_OFFSET_CAPTURE);
if (empty($match) === false) {
$url = ui_get_full_url(false, false, false, false).$vcClientPath.'/'.$match[0][0];
echo '<link rel="stylesheet" type="text/css" href="'.$url.'" />';
$url = $baseUrl.$vcClientPath.'/'.$match[0][0];
echo '<link type="text/css" rel="stylesheet" href="'.$url.'" />';
}
}
@ -215,19 +216,29 @@ if ($pure === true) {
</style>
<?php
}
ui_require_javascript_file('pandora_visual_console');
?>
<script type="text/javascript">
var container = document.getElementById("visual-console-container");
var props = <?php echo (string) $visualConsole; ?>;
var items = <?php echo '['.implode($visualConsoleItems, ',').']'; ?>;
if (container != null) {
try {
var visualConsole = new VisualConsole(container, props, items);
console.log(visualConsole);
} catch (error) {
console.log("ERROR", error.message);
}
var baseUrl = "<?php echo $config['homeurl']; ?>";
var handleUpdate = function (prevProps, newProps) {
// TODO: Change the view header and links to display id or name changes.
}
var visualConsole = createVisualConsole(
container,
props,
items,
baseUrl,
10000,
handleUpdate
);
$(document).ready(function () {
var controls = document.getElementById('vc-controls');
if (controls) autoHideElement(controls, 1000);
});
</script>