Merge branch 'ent-3975-mejorar-la-actualizacion-de-los-datos-y-elementos-de-la-consola-visual' into 'develop'
Mejorar la actualizacion de los datos y elementos de la consola visual See merge request artica/pandorafms!2429
This commit is contained in:
commit
5b286b4f67
|
@ -1,5 +1,5 @@
|
||||||
// TODO: Add Artica ST header.
|
// TODO: Add Artica ST header.
|
||||||
/* globals jQuery, VisualConsole */
|
/* globals jQuery, VisualConsole, AsyncTaskManager */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* *********************
|
* *********************
|
||||||
|
@ -28,63 +28,89 @@ function createVisualConsole(
|
||||||
updateInterval,
|
updateInterval,
|
||||||
onUpdate
|
onUpdate
|
||||||
) {
|
) {
|
||||||
var visualConsole = null;
|
|
||||||
var linkedVCRequest = null;
|
|
||||||
var updateVCRequest = null;
|
|
||||||
|
|
||||||
if (container == null || props == null || items == null) return null;
|
if (container == null || props == null || items == null) return null;
|
||||||
if (baseUrl == null) baseUrl = "";
|
if (baseUrl == null) baseUrl = "";
|
||||||
|
|
||||||
// Code which will be executed between intervals.
|
var visualConsole = null;
|
||||||
var intervalRef = null;
|
var asyncTaskManager = new AsyncTaskManager();
|
||||||
var stopInterval = function() {
|
|
||||||
if (intervalRef !== null) window.clearInterval(intervalRef);
|
|
||||||
};
|
|
||||||
var startInterval = function() {
|
|
||||||
if (updateInterval == null || updateInterval <= 0) return;
|
|
||||||
stopInterval();
|
|
||||||
|
|
||||||
intervalRef = window.setInterval(function() {
|
function updateVisualConsole(visualConsoleId, updateInterval, tts) {
|
||||||
if (updateVCRequest !== null) updateVCRequest.abort();
|
if (tts == null) tts = 0; // Time to start.
|
||||||
updateVCRequest = loadVisualConsoleData(
|
|
||||||
baseUrl,
|
asyncTaskManager.add(
|
||||||
visualConsole.props.id,
|
"visual-console",
|
||||||
function(error, data) {
|
function(done) {
|
||||||
if (error) {
|
var abortable = loadVisualConsoleData(
|
||||||
console.log(
|
baseUrl,
|
||||||
"[ERROR]",
|
visualConsoleId,
|
||||||
"[VISUAL-CONSOLE-CLIENT]",
|
function(error, data) {
|
||||||
"[API]",
|
if (error) {
|
||||||
error.message
|
console.log(
|
||||||
);
|
"[ERROR]",
|
||||||
return;
|
"[VISUAL-CONSOLE-CLIENT]",
|
||||||
|
"[API]",
|
||||||
|
error.message
|
||||||
|
);
|
||||||
|
done();
|
||||||
|
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
|
||||||
|
|
||||||
|
done();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
);
|
||||||
|
|
||||||
// Replace Visual Console.
|
return {
|
||||||
if (data != null && data.props != null && data.items != null) {
|
cancel: function() {
|
||||||
try {
|
abortable.abort();
|
||||||
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
|
||||||
|
);
|
||||||
|
|
||||||
|
asyncTaskManager.add("visual-console-start", function(done) {
|
||||||
|
var ref = setTimeout(function() {
|
||||||
|
asyncTaskManager.init("visual-console");
|
||||||
|
done();
|
||||||
|
}, tts);
|
||||||
|
|
||||||
|
return {
|
||||||
|
cancel: function() {
|
||||||
|
clearTimeout(ref);
|
||||||
}
|
}
|
||||||
);
|
};
|
||||||
}, updateInterval);
|
});
|
||||||
};
|
|
||||||
|
if (tts > 0) {
|
||||||
|
// Wait to start the fetch interval.
|
||||||
|
asyncTaskManager.init("visual-console-start");
|
||||||
|
} else {
|
||||||
|
// Start the fetch interval immediately.
|
||||||
|
asyncTaskManager.init("visual-console");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Initialize the Visual Console.
|
// Initialize the Visual Console.
|
||||||
try {
|
try {
|
||||||
|
@ -102,64 +128,35 @@ function createVisualConsole(
|
||||||
) {
|
) {
|
||||||
// Stop the current link behavior.
|
// Stop the current link behavior.
|
||||||
e.nativeEvent.preventDefault();
|
e.nativeEvent.preventDefault();
|
||||||
|
|
||||||
// Fetch and update the old VC with the new.
|
// Fetch and update the old VC with the new.
|
||||||
if (linkedVCRequest !== null) linkedVCRequest.abort();
|
updateVisualConsole(e.data.linkedLayoutId, updateInterval);
|
||||||
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.
|
if (updateInterval != null && updateInterval > 0) {
|
||||||
startInterval();
|
// Start an interval to update the Visual Console.
|
||||||
|
updateVisualConsole(props.id, updateInterval, updateInterval);
|
||||||
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log("[ERROR]", "[VISUAL-CONSOLE-CLIENT]", error.message);
|
console.log("[ERROR]", "[VISUAL-CONSOLE-CLIENT]", error.message);
|
||||||
}
|
}
|
||||||
|
|
||||||
return visualConsole;
|
return {
|
||||||
|
visualConsole: visualConsole,
|
||||||
|
changeUpdateInterval: function(updateInterval) {
|
||||||
|
if (updateInterval != null && updateInterval > 0) {
|
||||||
|
updateVisualConsole(
|
||||||
|
visualConsole.props.id,
|
||||||
|
updateInterval,
|
||||||
|
updateInterval
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
// Update interval disabled. Cancel possible pending tasks.
|
||||||
|
asyncTaskManager.cancel("visual-console");
|
||||||
|
asyncTaskManager.cancel("visual-console-start");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -13,16 +13,16 @@
|
||||||
display: flex;
|
display: flex;
|
||||||
-webkit-box-orient: initial;
|
-webkit-box-orient: initial;
|
||||||
-webkit-box-direction: initial;
|
-webkit-box-direction: initial;
|
||||||
-ms-flex-direction: initial;
|
-ms-flex-direction: initial;
|
||||||
flex-direction: initial;
|
flex-direction: initial;
|
||||||
justify-items: center;
|
justify-items: center;
|
||||||
-webkit-box-align: center;
|
-webkit-box-align: center;
|
||||||
-ms-flex-align: center;
|
-ms-flex-align: center;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
-webkit-user-select: text;
|
-webkit-user-select: text;
|
||||||
-moz-user-select: text;
|
-moz-user-select: text;
|
||||||
-ms-user-select: text;
|
-ms-user-select: text;
|
||||||
user-select: text;
|
user-select: text;
|
||||||
}
|
}
|
||||||
|
|
||||||
@font-face {
|
@font-face {
|
||||||
|
@ -38,17 +38,17 @@
|
||||||
display: flex;
|
display: flex;
|
||||||
-webkit-box-orient: vertical;
|
-webkit-box-orient: vertical;
|
||||||
-webkit-box-direction: normal;
|
-webkit-box-direction: normal;
|
||||||
-ms-flex-direction: column;
|
-ms-flex-direction: column;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
-webkit-box-pack: center;
|
-webkit-box-pack: center;
|
||||||
-ms-flex-pack: center;
|
-ms-flex-pack: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
justify-items: center;
|
justify-items: center;
|
||||||
-ms-flex-line-pack: center;
|
-ms-flex-line-pack: center;
|
||||||
align-content: center;
|
align-content: center;
|
||||||
-webkit-box-align: center;
|
-webkit-box-align: center;
|
||||||
-ms-flex-align: center;
|
-ms-flex-align: center;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.visual-console-item .digital-clock > span {
|
.visual-console-item .digital-clock > span {
|
||||||
|
@ -78,17 +78,18 @@
|
||||||
|
|
||||||
.visual-console-item .analogic-clock .hour-hand {
|
.visual-console-item .analogic-clock .hour-hand {
|
||||||
-webkit-animation: rotate-hour 43200s infinite linear;
|
-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 {
|
.visual-console-item .analogic-clock .minute-hand {
|
||||||
-webkit-animation: rotate-minute 3600s infinite linear;
|
-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 {
|
.visual-console-item .analogic-clock .second-hand {
|
||||||
-webkit-animation: rotate-second 60s infinite linear;
|
-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*/
|
|
@ -1 +1 @@
|
||||||
{"version":3,"sources":["webpack:///main.css","webpack:///styles.css"],"names":[],"mappings":"AAAA;EACE,gBAAgB;EAChB,kBAAkB;EAClB,4BAA4B;EAC5B,wBAAwB;AAC1B;;AAEA;EACE,kBAAkB;EAClB,oBAAa;EAAb,oBAAa;EAAb,aAAa;EACb,2BAAuB;EAAvB,8BAAuB;MAAvB,2BAAuB;UAAvB,uBAAuB;EACvB,qBAAqB;EACrB,yBAAmB;MAAnB,sBAAmB;UAAnB,mBAAmB;EACnB,yBAAiB;KAAjB,sBAAiB;MAAjB,qBAAiB;UAAjB,iBAAiB;AACnB;;ACdA;EACE,wBAAwB;EACxB,0BAA2B;AAC7B;;AAEA,kBAAkB;;AAElB;EACE,oBAAa;EAAb,oBAAa;EAAb,aAAa;EACb,4BAAsB;EAAtB,6BAAsB;MAAtB,0BAAsB;UAAtB,sBAAsB;EACtB,wBAAuB;MAAvB,qBAAuB;UAAvB,uBAAuB;EACvB,qBAAqB;EACrB,0BAAqB;MAArB,qBAAqB;EACrB,yBAAmB;MAAnB,sBAAmB;UAAnB,mBAAmB;AACrB;;AAEA;EACE,6DAA6D;EAC7D,eAAe;;EAEf,0BAA0B;EAC1B,mCAAmC;EACnC,kCAAkC;EAClC,kCAAkC;EAClC,wCAAwC;AAC1C;;AAEA;EACE,eAAe;AACjB;;AAEA;EACE,eAAe;AACjB;;AAEA,iBAAiB;;AAEjB;EACE,kBAAkB;AACpB;;AAEA;EACE,qDAA6C;UAA7C,6CAA6C;AAC/C;;AAEA;EACE,sDAA8C;UAA9C,8CAA8C;AAChD;;AAEA;EACE,oDAA4C;UAA5C,4CAA4C;AAC9C","file":"vc.main.css","sourcesContent":["#visual-console-container {\n margin: 0px auto;\n position: relative;\n background-repeat: no-repeat;\n background-size: contain;\n}\n\n.visual-console-item {\n position: absolute;\n display: flex;\n flex-direction: initial;\n justify-items: center;\n align-items: center;\n user-select: text;\n}\n","@font-face {\n font-family: Alarm Clock;\n src: url(./alarm-clock.ttf);\n}\n\n/* Digital clock */\n\n.visual-console-item .digital-clock {\n display: flex;\n flex-direction: column;\n justify-content: center;\n justify-items: center;\n align-content: center;\n align-items: center;\n}\n\n.visual-console-item .digital-clock > span {\n font-family: \"Alarm Clock\", \"Courier New\", Courier, monospace;\n font-size: 50px;\n\n /* To improve legibility */\n -webkit-font-smoothing: antialiased;\n -moz-osx-font-smoothing: grayscale;\n text-rendering: optimizeLegibility;\n text-shadow: rgba(0, 0, 0, 0.01) 0 0 1px;\n}\n\n.visual-console-item .digital-clock > span.date {\n font-size: 25px;\n}\n\n.visual-console-item .digital-clock > span.timezone {\n font-size: 25px;\n}\n\n/* Analog clock */\n\n.visual-console-item .analogic-clock {\n text-align: center;\n}\n\n.visual-console-item .analogic-clock .hour-hand {\n animation: rotate-hour 43200s infinite linear;\n}\n\n.visual-console-item .analogic-clock .minute-hand {\n animation: rotate-minute 3600s infinite linear;\n}\n\n.visual-console-item .analogic-clock .second-hand {\n animation: rotate-second 60s infinite linear;\n}\n"],"sourceRoot":""}
|
{"version":3,"sources":["webpack:///main.css","webpack:///styles.css"],"names":[],"mappings":"AAAA;EACE,gBAAgB;EAChB,kBAAkB;EAClB,4BAA4B;EAC5B,0BAA0B;EAC1B,2BAA2B;AAC7B;;AAEA;EACE,kBAAkB;EAClB,oBAAa;EAAb,oBAAa;EAAb,aAAa;EACb,2BAAuB;EAAvB,8BAAuB;MAAvB,2BAAuB;UAAvB,uBAAuB;EACvB,qBAAqB;EACrB,yBAAmB;MAAnB,sBAAmB;UAAnB,mBAAmB;EACnB,yBAAiB;KAAjB,sBAAiB;MAAjB,qBAAiB;UAAjB,iBAAiB;AACnB;;ACfA;EACE,wBAAwB;EACxB,0BAA2B;AAC7B;;AAEA,kBAAkB;;AAElB;EACE,oBAAa;EAAb,oBAAa;EAAb,aAAa;EACb,4BAAsB;EAAtB,6BAAsB;MAAtB,0BAAsB;UAAtB,sBAAsB;EACtB,wBAAuB;MAAvB,qBAAuB;UAAvB,uBAAuB;EACvB,qBAAqB;EACrB,0BAAqB;MAArB,qBAAqB;EACrB,yBAAmB;MAAnB,sBAAmB;UAAnB,mBAAmB;AACrB;;AAEA;EACE,6DAA6D;EAC7D,eAAe;;EAEf,0BAA0B;EAC1B,mCAAmC;EACnC,kCAAkC;EAClC,kCAAkC;EAClC,wCAAwC;AAC1C;;AAEA;EACE,eAAe;AACjB;;AAEA;EACE,eAAe;AACjB;;AAEA,iBAAiB;;AAEjB;EACE,kBAAkB;AACpB;;AAEA;EACE,qDAA6C;UAA7C,6CAA6C;AAC/C;;AAEA;EACE,sDAA8C;UAA9C,8CAA8C;AAChD;;AAEA;EACE,oDAA4C;UAA5C,4CAA4C;AAC9C","file":"vc.main.css","sourcesContent":["#visual-console-container {\n margin: 0px auto;\n position: relative;\n background-repeat: no-repeat;\n background-size: 100% 100%;\n background-position: center;\n}\n\n.visual-console-item {\n position: absolute;\n display: flex;\n flex-direction: initial;\n justify-items: center;\n align-items: center;\n user-select: text;\n}\n","@font-face {\n font-family: Alarm Clock;\n src: url(./alarm-clock.ttf);\n}\n\n/* Digital clock */\n\n.visual-console-item .digital-clock {\n display: flex;\n flex-direction: column;\n justify-content: center;\n justify-items: center;\n align-content: center;\n align-items: center;\n}\n\n.visual-console-item .digital-clock > span {\n font-family: \"Alarm Clock\", \"Courier New\", Courier, monospace;\n font-size: 50px;\n\n /* To improve legibility */\n -webkit-font-smoothing: antialiased;\n -moz-osx-font-smoothing: grayscale;\n text-rendering: optimizeLegibility;\n text-shadow: rgba(0, 0, 0, 0.01) 0 0 1px;\n}\n\n.visual-console-item .digital-clock > span.date {\n font-size: 25px;\n}\n\n.visual-console-item .digital-clock > span.timezone {\n font-size: 25px;\n}\n\n/* Analog clock */\n\n.visual-console-item .analogic-clock {\n text-align: center;\n}\n\n.visual-console-item .analogic-clock .hour-hand {\n animation: rotate-hour 43200s infinite linear;\n}\n\n.visual-console-item .analogic-clock .minute-hand {\n animation: rotate-minute 3600s infinite linear;\n}\n\n.visual-console-item .analogic-clock .second-hand {\n animation: rotate-second 60s infinite linear;\n}\n"],"sourceRoot":""}
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -97,7 +97,17 @@ echo '<li class="nomn">';
|
||||||
echo '<div class="vc-refr">';
|
echo '<div class="vc-refr">';
|
||||||
echo '<div id="vc-refr-form">';
|
echo '<div id="vc-refr-form">';
|
||||||
echo __('Refresh').':';
|
echo __('Refresh').':';
|
||||||
echo html_print_select(get_refresh_time_array(), 'refr', $refr, '', '', 0, true, false, false);
|
echo html_print_select(
|
||||||
|
get_refresh_time_array(),
|
||||||
|
'vc-refr',
|
||||||
|
$refr,
|
||||||
|
'',
|
||||||
|
'',
|
||||||
|
0,
|
||||||
|
true,
|
||||||
|
false,
|
||||||
|
false
|
||||||
|
);
|
||||||
echo '</div>';
|
echo '</div>';
|
||||||
echo '</div>';
|
echo '</div>';
|
||||||
echo '</li>';
|
echo '</li>';
|
||||||
|
@ -188,7 +198,7 @@ $visualConsoleItems = VisualConsole::getItemsFromDB(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var visualConsole = createVisualConsole(
|
var visualConsoleManager = createVisualConsole(
|
||||||
container,
|
container,
|
||||||
props,
|
props,
|
||||||
items,
|
items,
|
||||||
|
@ -197,13 +207,20 @@ $visualConsoleItems = VisualConsole::getItemsFromDB(
|
||||||
handleUpdate
|
handleUpdate
|
||||||
);
|
);
|
||||||
|
|
||||||
$(document).ready (function () {
|
// Update the data fetch interval.
|
||||||
var refr = <?php echo (int) $refr; ?>;
|
$('select#vc-refr').change(function(event) {
|
||||||
var href = "<?php echo ui_get_url_refresh($ignored_params); ?>";
|
var refr = Number.parseInt(event.target.value);
|
||||||
|
|
||||||
$('select#refr').change(function (event) {
|
if (!Number.isNaN(refr)) {
|
||||||
url = js_html_entity_decode( href ) + $('select#refr').val();
|
visualConsoleManager.changeUpdateInterval(refr * 1000); // To ms.
|
||||||
$(document).attr ("location", url);
|
|
||||||
});
|
// Change the URL (if the browser has support).
|
||||||
|
if ("history" in window) {
|
||||||
|
var regex = /(refr=)\d+(&?)/gi;
|
||||||
|
var replacement = '$1' + refr + '$2';
|
||||||
|
var href = window.location.href.replace(regex, replacement);
|
||||||
|
window.history.replaceState({}, document.title, href);
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -177,7 +177,17 @@ if ($pure === true) {
|
||||||
echo '<div class="vc-refr">';
|
echo '<div class="vc-refr">';
|
||||||
echo '<div id="vc-refr-form">';
|
echo '<div id="vc-refr-form">';
|
||||||
echo __('Refresh').':';
|
echo __('Refresh').':';
|
||||||
echo html_print_select(get_refresh_time_array(), 'refr', $refr, '', '', 0, true, false, false);
|
echo html_print_select(
|
||||||
|
get_refresh_time_array(),
|
||||||
|
'vc-refr',
|
||||||
|
$refr,
|
||||||
|
'',
|
||||||
|
'',
|
||||||
|
0,
|
||||||
|
true,
|
||||||
|
false,
|
||||||
|
false
|
||||||
|
);
|
||||||
echo '</div>';
|
echo '</div>';
|
||||||
echo '</div>';
|
echo '</div>';
|
||||||
echo '</li>';
|
echo '</li>';
|
||||||
|
@ -296,7 +306,7 @@ $visualConsoleItems = VisualConsole::getItemsFromDB(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var visualConsole = createVisualConsole(
|
var visualConsoleManager = createVisualConsole(
|
||||||
container,
|
container,
|
||||||
props,
|
props,
|
||||||
items,
|
items,
|
||||||
|
@ -305,16 +315,20 @@ $visualConsoleItems = VisualConsole::getItemsFromDB(
|
||||||
handleUpdate
|
handleUpdate
|
||||||
);
|
);
|
||||||
|
|
||||||
$(document).ready (function () {
|
// Update the data fetch interval.
|
||||||
var refr = <?php echo (int) $refr; ?>;
|
$('select#vc-refr').change(function(event) {
|
||||||
var pure = <?php echo (int) $config['pure']; ?>;
|
var refr = Number.parseInt(event.target.value);
|
||||||
var href = "<?php echo ui_get_url_refresh($ignored_params); ?>";
|
|
||||||
|
|
||||||
if (pure) {
|
if (!Number.isNaN(refr)) {
|
||||||
$('select#refr').change(function (event) {
|
visualConsoleManager.changeUpdateInterval(refr * 1000); // To ms.
|
||||||
url = js_html_entity_decode( href ) + $('select#refr').val();
|
|
||||||
$(document).attr ("location", url);
|
// Change the URL (if the browser has support).
|
||||||
});
|
if ("history" in window) {
|
||||||
|
var regex = /(refr=)\d+(&?)/gi;
|
||||||
|
var replacement = '$1' + refr + '$2';
|
||||||
|
var href = window.location.href.replace(regex, replacement);
|
||||||
|
window.history.replaceState({}, document.title, href);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -67,7 +67,7 @@ export interface ItemRemoveEvent<Props extends ItemProps> {
|
||||||
* @param labelPosition Raw value.
|
* @param labelPosition Raw value.
|
||||||
*/
|
*/
|
||||||
const parseLabelPosition = (
|
const parseLabelPosition = (
|
||||||
labelPosition: any // eslint-disable-line @typescript-eslint/no-explicit-any
|
labelPosition: unknown
|
||||||
): ItemProps["labelPosition"] => {
|
): ItemProps["labelPosition"] => {
|
||||||
switch (labelPosition) {
|
switch (labelPosition) {
|
||||||
case "up":
|
case "up":
|
||||||
|
|
|
@ -7,8 +7,12 @@
|
||||||
|
|
||||||
import "./main.css"; // CSS import.
|
import "./main.css"; // CSS import.
|
||||||
import VisualConsole from "./VisualConsole";
|
import VisualConsole from "./VisualConsole";
|
||||||
|
import AsyncTaskManager from "./lib/AsyncTaskManager";
|
||||||
|
|
||||||
// Export the VisualConsole class to the global object.
|
// Export the VisualConsole class to the global object.
|
||||||
|
|
||||||
// eslint-disable-next-line
|
// eslint-disable-next-line
|
||||||
(window as any).VisualConsole = VisualConsole;
|
(window as any).VisualConsole = VisualConsole;
|
||||||
|
|
||||||
|
// Export the AsyncTaskManager class to the global object.
|
||||||
|
// eslint-disable-next-line
|
||||||
|
(window as any).AsyncTaskManager = AsyncTaskManager;
|
||||||
|
|
|
@ -27,9 +27,7 @@ export type ClockProps = {
|
||||||
* Extract a valid enum value from a raw unknown value.
|
* Extract a valid enum value from a raw unknown value.
|
||||||
* @param clockType Raw value.
|
* @param clockType Raw value.
|
||||||
*/
|
*/
|
||||||
const parseClockType = (
|
const parseClockType = (clockType: unknown): ClockProps["clockType"] => {
|
||||||
clockType: any // eslint-disable-line @typescript-eslint/no-explicit-any
|
|
||||||
): ClockProps["clockType"] => {
|
|
||||||
switch (clockType) {
|
switch (clockType) {
|
||||||
case "analogic":
|
case "analogic":
|
||||||
case "digital":
|
case "digital":
|
||||||
|
@ -43,12 +41,9 @@ const parseClockType = (
|
||||||
* Extract a valid enum value from a raw unknown value.
|
* Extract a valid enum value from a raw unknown value.
|
||||||
* @param clockFormat Raw value.
|
* @param clockFormat Raw value.
|
||||||
*/
|
*/
|
||||||
const parseClockFormat = (
|
const parseClockFormat = (clockFormat: unknown): ClockProps["clockFormat"] => {
|
||||||
clockFormat: any // eslint-disable-line @typescript-eslint/no-explicit-any
|
|
||||||
): ClockProps["clockFormat"] => {
|
|
||||||
switch (clockFormat) {
|
switch (clockFormat) {
|
||||||
case "datetime":
|
case "datetime":
|
||||||
case "date":
|
|
||||||
case "time":
|
case "time":
|
||||||
return clockFormat;
|
return clockFormat;
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -36,8 +36,9 @@ export type PercentileProps = {
|
||||||
* Extract a valid enum value from a raw type value.
|
* Extract a valid enum value from a raw type value.
|
||||||
* @param type Raw value.
|
* @param type Raw value.
|
||||||
*/
|
*/
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
function extractPercentileType(
|
||||||
function extractPercentileType(type: any): PercentileProps["percentileType"] {
|
type: unknown
|
||||||
|
): PercentileProps["percentileType"] {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case "progress-bar":
|
case "progress-bar":
|
||||||
case "bubble":
|
case "bubble":
|
||||||
|
@ -60,8 +61,7 @@ function extractPercentileType(type: any): PercentileProps["percentileType"] {
|
||||||
* Extract a valid enum value from a raw value type value.
|
* Extract a valid enum value from a raw value type value.
|
||||||
* @param type Raw value.
|
* @param type Raw value.
|
||||||
*/
|
*/
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
function extractValueType(valueType: unknown): PercentileProps["valueType"] {
|
||||||
function extractValueType(valueType: any): PercentileProps["valueType"] {
|
|
||||||
switch (valueType) {
|
switch (valueType) {
|
||||||
case "percent":
|
case "percent":
|
||||||
case "value":
|
case "value":
|
||||||
|
|
|
@ -31,9 +31,7 @@ export type SimpleValueProps = {
|
||||||
* Extract a valid enum value from a raw value type.
|
* Extract a valid enum value from a raw value type.
|
||||||
* @param valueType Raw value.
|
* @param valueType Raw value.
|
||||||
*/
|
*/
|
||||||
const parseValueType = (
|
const parseValueType = (valueType: unknown): SimpleValueProps["valueType"] => {
|
||||||
valueType: any // eslint-disable-line @typescript-eslint/no-explicit-any
|
|
||||||
): SimpleValueProps["valueType"] => {
|
|
||||||
switch (valueType) {
|
switch (valueType) {
|
||||||
case "string":
|
case "string":
|
||||||
case "image":
|
case "image":
|
||||||
|
@ -48,7 +46,7 @@ const parseValueType = (
|
||||||
* @param processValue Raw value.
|
* @param processValue Raw value.
|
||||||
*/
|
*/
|
||||||
const parseProcessValue = (
|
const parseProcessValue = (
|
||||||
processValue: any // eslint-disable-line @typescript-eslint/no-explicit-any
|
processValue: unknown
|
||||||
): SimpleValueProps["processValue"] => {
|
): SimpleValueProps["processValue"] => {
|
||||||
switch (processValue) {
|
switch (processValue) {
|
||||||
case "none":
|
case "none":
|
||||||
|
|
|
@ -25,7 +25,7 @@ export type StaticGraphProps = {
|
||||||
* @param showLastValueTooltip Raw value.
|
* @param showLastValueTooltip Raw value.
|
||||||
*/
|
*/
|
||||||
const parseShowLastValueTooltip = (
|
const parseShowLastValueTooltip = (
|
||||||
showLastValueTooltip: any // eslint-disable-line @typescript-eslint/no-explicit-any
|
showLastValueTooltip: unknown
|
||||||
): StaticGraphProps["showLastValueTooltip"] => {
|
): StaticGraphProps["showLastValueTooltip"] => {
|
||||||
switch (showLastValueTooltip) {
|
switch (showLastValueTooltip) {
|
||||||
case "default":
|
case "default":
|
||||||
|
|
|
@ -0,0 +1,172 @@
|
||||||
|
import TypedEvent, { Disposable, Listener } from "../TypedEvent";
|
||||||
|
|
||||||
|
interface Cancellable {
|
||||||
|
cancel(): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
type AsyncTaskStatus = "waiting" | "started" | "cancelled" | "finished";
|
||||||
|
type AsyncTaskInitiator = (done: () => void) => Cancellable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines an async task which can be started and cancelled.
|
||||||
|
* It's possible to observe the status changes of the task.
|
||||||
|
*/
|
||||||
|
class AsyncTask {
|
||||||
|
private readonly taskInitiator: AsyncTaskInitiator;
|
||||||
|
private cancellable: Cancellable = { cancel: () => {} };
|
||||||
|
private _status: AsyncTaskStatus = "waiting";
|
||||||
|
|
||||||
|
// Event manager for status change events.
|
||||||
|
private readonly statusChangeEventManager = new TypedEvent<AsyncTaskStatus>();
|
||||||
|
// List of references to clean the event listeners.
|
||||||
|
private readonly disposables: Disposable[] = [];
|
||||||
|
|
||||||
|
public constructor(taskInitiator: AsyncTaskInitiator) {
|
||||||
|
this.taskInitiator = taskInitiator;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Public setter of the `status` property.
|
||||||
|
* @param status.
|
||||||
|
*/
|
||||||
|
public set status(status: AsyncTaskStatus) {
|
||||||
|
this._status = status;
|
||||||
|
this.statusChangeEventManager.emit(status);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Public accessor of the `status` property.
|
||||||
|
* @return status.
|
||||||
|
*/
|
||||||
|
public get status() {
|
||||||
|
return this._status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Start the async task.
|
||||||
|
*/
|
||||||
|
public init(): void {
|
||||||
|
this.cancellable = this.taskInitiator(() => {
|
||||||
|
this.status = "finished";
|
||||||
|
});
|
||||||
|
this.status = "started";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cancel the async task.
|
||||||
|
*/
|
||||||
|
public cancel(): void {
|
||||||
|
this.cancellable.cancel();
|
||||||
|
this.status = "cancelled";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add an event handler to the status change.
|
||||||
|
* @param listener Function which is going to be executed when the status changes.
|
||||||
|
*/
|
||||||
|
public onStatusChange(listener: Listener<AsyncTaskStatus>): 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.statusChangeEventManager.on(listener);
|
||||||
|
this.disposables.push(disposable);
|
||||||
|
|
||||||
|
return disposable;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wrap an async task into another which will execute that task indefinitely
|
||||||
|
* every time the tash finnish and the chosen period ends.
|
||||||
|
* Will last until cancellation.
|
||||||
|
*
|
||||||
|
* @param task Async task to execute.
|
||||||
|
* @param period Time in milliseconds to wait until the next async esecution.
|
||||||
|
*
|
||||||
|
* @return A new async task.
|
||||||
|
*/
|
||||||
|
function asyncPeriodic(task: AsyncTask, period: number): AsyncTask {
|
||||||
|
return new AsyncTask(() => {
|
||||||
|
let ref: number | null = null;
|
||||||
|
|
||||||
|
task.onStatusChange(status => {
|
||||||
|
if (status === "finished") {
|
||||||
|
ref = window.setTimeout(() => {
|
||||||
|
task.init();
|
||||||
|
}, period);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
task.init();
|
||||||
|
|
||||||
|
return {
|
||||||
|
cancel: () => {
|
||||||
|
if (ref) clearTimeout(ref);
|
||||||
|
task.cancel();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Manages a list of async tasks.
|
||||||
|
*/
|
||||||
|
export default class AsyncTaskManager {
|
||||||
|
private tasks: { [identifier: string]: AsyncTask } = {};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds an async task to the manager.
|
||||||
|
*
|
||||||
|
* @param identifier Unique identifier.
|
||||||
|
* @param taskInitiator Function to initialize the async task.
|
||||||
|
* Should return a structure to cancel the task.
|
||||||
|
* @param period Optional period to repeat the task indefinitely.
|
||||||
|
*/
|
||||||
|
public add(
|
||||||
|
identifier: string,
|
||||||
|
taskInitiator: AsyncTaskInitiator,
|
||||||
|
period: number = 0
|
||||||
|
): AsyncTask {
|
||||||
|
if (this.tasks[identifier] && this.tasks[identifier].status === "started") {
|
||||||
|
this.tasks[identifier].cancel();
|
||||||
|
}
|
||||||
|
|
||||||
|
const asyncTask =
|
||||||
|
period > 0
|
||||||
|
? asyncPeriodic(new AsyncTask(taskInitiator), period)
|
||||||
|
: new AsyncTask(taskInitiator);
|
||||||
|
|
||||||
|
this.tasks[identifier] = asyncTask;
|
||||||
|
|
||||||
|
return this.tasks[identifier];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Starts an async task.
|
||||||
|
*
|
||||||
|
* @param identifier Unique identifier.
|
||||||
|
*/
|
||||||
|
public init(identifier: string) {
|
||||||
|
if (
|
||||||
|
this.tasks[identifier] &&
|
||||||
|
(this.tasks[identifier].status === "waiting" ||
|
||||||
|
this.tasks[identifier].status === "cancelled" ||
|
||||||
|
this.tasks[identifier].status === "finished")
|
||||||
|
) {
|
||||||
|
this.tasks[identifier].init();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cancel a running async task.
|
||||||
|
*
|
||||||
|
* @param identifier Unique identifier.
|
||||||
|
*/
|
||||||
|
public cancel(identifier: string) {
|
||||||
|
if (this.tasks[identifier] && this.tasks[identifier].status === "started") {
|
||||||
|
this.tasks[identifier].cancel();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -6,7 +6,7 @@ import {
|
||||||
WithModuleProps,
|
WithModuleProps,
|
||||||
LinkedVisualConsoleProps,
|
LinkedVisualConsoleProps,
|
||||||
LinkedVisualConsolePropsStatus
|
LinkedVisualConsolePropsStatus
|
||||||
} from "./types";
|
} from "../types";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return a number or a default value from a raw value.
|
* Return a number or a default value from a raw value.
|
||||||
|
@ -14,8 +14,7 @@ import {
|
||||||
* @param defaultValue Default value to use if we cannot extract a valid number.
|
* @param defaultValue Default value to use if we cannot extract a valid number.
|
||||||
* @return A valid number or the default value.
|
* @return A valid number or the default value.
|
||||||
*/
|
*/
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
export function parseIntOr<T>(value: unknown, defaultValue: T): number | T {
|
||||||
export function parseIntOr<T>(value: any, defaultValue: T): number | T {
|
|
||||||
if (typeof value === "number") return value;
|
if (typeof value === "number") return value;
|
||||||
if (typeof value === "string" && value.length > 0 && !isNaN(parseInt(value)))
|
if (typeof value === "string" && value.length > 0 && !isNaN(parseInt(value)))
|
||||||
return parseInt(value);
|
return parseInt(value);
|
||||||
|
@ -28,8 +27,7 @@ export function parseIntOr<T>(value: any, defaultValue: T): number | T {
|
||||||
* @param defaultValue Default value to use if we cannot extract a valid number.
|
* @param defaultValue Default value to use if we cannot extract a valid number.
|
||||||
* @return A valid number or the default value.
|
* @return A valid number or the default value.
|
||||||
*/
|
*/
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
export function parseFloatOr<T>(value: unknown, defaultValue: T): number | T {
|
||||||
export function parseFloatOr<T>(value: any, defaultValue: T): number | T {
|
|
||||||
if (typeof value === "number") return value;
|
if (typeof value === "number") return value;
|
||||||
if (
|
if (
|
||||||
typeof value === "string" &&
|
typeof value === "string" &&
|
||||||
|
@ -55,8 +53,10 @@ export function stringIsEmpty(value?: string | null): boolean {
|
||||||
* @param defaultValue Default value to use if we cannot extract a non empty string.
|
* @param defaultValue Default value to use if we cannot extract a non empty string.
|
||||||
* @return A non empty string or the default value.
|
* @return A non empty string or the default value.
|
||||||
*/
|
*/
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
export function notEmptyStringOr<T>(
|
||||||
export function notEmptyStringOr<T>(value: any, defaultValue: T): string | T {
|
value: unknown,
|
||||||
|
defaultValue: T
|
||||||
|
): string | T {
|
||||||
return typeof value === "string" && value.length > 0 ? value : defaultValue;
|
return typeof value === "string" && value.length > 0 ? value : defaultValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -65,8 +65,7 @@ export function notEmptyStringOr<T>(value: any, defaultValue: T): string | T {
|
||||||
* @param value Raw value from which we will try to extract the boolean.
|
* @param value Raw value from which we will try to extract the boolean.
|
||||||
* @return A valid boolean value. false by default.
|
* @return A valid boolean value. false by default.
|
||||||
*/
|
*/
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
export function parseBoolean(value: unknown): boolean {
|
||||||
export function parseBoolean(value: any): boolean {
|
|
||||||
if (typeof value === "boolean") return value;
|
if (typeof value === "boolean") return value;
|
||||||
else if (typeof value === "number") return value > 0;
|
else if (typeof value === "number") return value > 0;
|
||||||
else if (typeof value === "string") return value === "1" || value === "true";
|
else if (typeof value === "string") return value === "1" || value === "true";
|
|
@ -8,7 +8,7 @@ import {
|
||||||
humanDate,
|
humanDate,
|
||||||
humanTime,
|
humanTime,
|
||||||
replaceMacros
|
replaceMacros
|
||||||
} from "./lib";
|
} from ".";
|
||||||
|
|
||||||
describe("function parseIntOr", () => {
|
describe("function parseIntOr", () => {
|
||||||
it("should retrieve valid int or a default value", () => {
|
it("should retrieve valid int or a default value", () => {
|
Loading…
Reference in New Issue