menu fixes with min lines of code and standard menus - WORKING-
This commit is contained in:
7
dependencies/measurement/measurement.js
vendored
7
dependencies/measurement/measurement.js
vendored
@@ -39,14 +39,15 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
const EventEmitter = require('events');
|
const EventEmitter = require('events');
|
||||||
const {logger,configUtils} = require('generalFunctions');
|
const {logger,configUtils,configManager} = require('generalFunctions');
|
||||||
const defaultConfig = require('./measurementConfig.json');
|
|
||||||
|
|
||||||
class Measurement {
|
class Measurement {
|
||||||
constructor(config={}) {
|
constructor(config={}) {
|
||||||
|
|
||||||
this.emitter = new EventEmitter(); // Own EventEmitter
|
this.emitter = new EventEmitter(); // Own EventEmitter
|
||||||
this.configUtils = new configUtils(defaultConfig);
|
this.configManager = new configManager();
|
||||||
|
this.defaultConfig = this.configManager.getConfig('measurement');
|
||||||
|
this.configUtils = new configUtils(this.defaultConfig);
|
||||||
this.config = this.configUtils.initConfig(config);
|
this.config = this.configUtils.initConfig(config);
|
||||||
|
|
||||||
// Init after config is set
|
// Init after config is set
|
||||||
|
|||||||
Binary file not shown.
147
measurement.html
147
measurement.html
@@ -1,11 +1,10 @@
|
|||||||
|
|
||||||
<script src="measurement/resources/menuUtils.js"></script>
|
<script src="/measurement/menu.js"></script>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
RED.nodes.registerType("measurement", {
|
RED.nodes.registerType("measurement", {
|
||||||
|
|
||||||
category: "digital twin",
|
category: "digital twin",
|
||||||
color: "#e4a363",
|
color: "#e4a363",
|
||||||
|
|
||||||
defaults: {
|
defaults: {
|
||||||
|
|
||||||
// Define default properties
|
// Define default properties
|
||||||
@@ -21,107 +20,38 @@
|
|||||||
o_min: { value: 0, required: true },
|
o_min: { value: 0, required: true },
|
||||||
o_max: { value: 1, required: true },
|
o_max: { value: 1, required: true },
|
||||||
simulator: { value: false },
|
simulator: { value: false },
|
||||||
unit: { value: "unit", required: true },
|
|
||||||
smooth_method: { value: "" },
|
smooth_method: { value: "" },
|
||||||
count: { value: "10", required: true },
|
count: { value: "10", required: true },
|
||||||
|
|
||||||
//define asset properties
|
//define asset properties
|
||||||
supplier: { value: "" },
|
supplier: { value: "" },
|
||||||
subType: { value: "" },
|
category: { value: "" },
|
||||||
|
assetType: { value: "" },
|
||||||
model: { value: "" },
|
model: { value: "" },
|
||||||
unit: { value: "" },
|
unit: { value: "" },
|
||||||
|
|
||||||
},
|
},
|
||||||
|
|
||||||
inputs: 1,
|
inputs: 1,
|
||||||
outputs: 4,
|
outputs: 3,
|
||||||
inputLabels: ["Measurement Input"],
|
inputLabels: ["Measurement Input"],
|
||||||
outputLabels: ["process", "dbase", "upstreamParent", "downstreamParent"],
|
outputLabels: ["process", "dbase", "parent"],
|
||||||
icon: "font-awesome/fa-tachometer",
|
icon: "font-awesome/fa-tachometer",
|
||||||
|
|
||||||
label: function () {
|
label: function () {
|
||||||
return this.name || "Measurement";
|
return this.name || "Measurement";
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
oneditprepare: function() {
|
oneditprepare: function() {
|
||||||
|
const waitForMenuData = () => {
|
||||||
const node = this;
|
if (window.EVOLV?.nodes?.measurement?.initEditor) {
|
||||||
|
window.EVOLV.nodes.measurement.initEditor(this);
|
||||||
// Use the namespaced version instead of global
|
} else {
|
||||||
const menuUtils = window.EVOLV.nodes.measurement.utils.menuUtils;
|
setTimeout(waitForMenuData, 50);
|
||||||
const helpers = window.EVOLV.nodes.measurement.utils.helpers;
|
}
|
||||||
//this needs to live somewhere and for now we add it to every node file for simplicity
|
|
||||||
const projecSettingstURL = "http://localhost:1880/generalFunctions/settings/projectSettings.json";
|
|
||||||
|
|
||||||
// Define UI html elements
|
|
||||||
const elements = {
|
|
||||||
// Basic fields
|
|
||||||
name: document.getElementById("node-input-name"),
|
|
||||||
// specific fields
|
|
||||||
scalingCheckbox: document.getElementById("node-input-scaling"),
|
|
||||||
rowInputMin: document.getElementById("row-input-i_min"),
|
|
||||||
rowInputMax: document.getElementById("row-input-i_max"),
|
|
||||||
smoothMethod: document.getElementById("node-input-smooth_method"),
|
|
||||||
count: document.getElementById("node-input-count"),
|
|
||||||
iOffset: document.getElementById("node-input-i_offset"),
|
|
||||||
oMin: document.getElementById("node-input-o_min"),
|
|
||||||
oMax: document.getElementById("node-input-o_max"),
|
|
||||||
// Logging fields
|
|
||||||
logCheckbox: document.getElementById("node-input-enableLog"),
|
|
||||||
logLevelSelect: document.getElementById("node-input-logLevel"),
|
|
||||||
rowLogLevel: document.getElementById("row-logLevel"),
|
|
||||||
// Asset fields
|
|
||||||
supplier: document.getElementById("node-input-supplier"),
|
|
||||||
subType: document.getElementById("node-input-subType"),
|
|
||||||
model: document.getElementById("node-input-model"),
|
|
||||||
unit: document.getElementById("node-input-unit"),
|
|
||||||
};
|
};
|
||||||
|
waitForMenuData();
|
||||||
|
|
||||||
|
|
||||||
try{
|
|
||||||
|
|
||||||
// Fetch project settings
|
|
||||||
menuUtils.fetchProjectData(projecSettingstURL)
|
|
||||||
.then((projectSettings) => {
|
|
||||||
|
|
||||||
//assign to node vars
|
|
||||||
node.configUrls = projectSettings.configUrls;
|
|
||||||
|
|
||||||
const { cloudConfigURL, localConfigURL } = menuUtils.getSpecificConfigUrl("measurement",node.configUrls.cloud.taggcodeAPI);
|
|
||||||
node.configUrls.cloud.config = cloudConfigURL; // first call
|
|
||||||
node.configUrls.local.config = localConfigURL; // backup call
|
|
||||||
|
|
||||||
node.locationId = projectSettings.locationId;
|
|
||||||
node.uuid = projectSettings.uuid;
|
|
||||||
|
|
||||||
// Gets the ID of the active workspace (Flow)
|
|
||||||
const activeFlowId = RED.workspaces.active(); //fetches active flow id
|
|
||||||
node.processId = 1;//activeFlowId;
|
|
||||||
|
|
||||||
|
|
||||||
// UI elements specific for node
|
|
||||||
menuUtils.initMeasurementToggles(elements);
|
|
||||||
menuUtils.populateSmoothingMethods(node.configUrls, elements, node);
|
|
||||||
// UI elements across all nodes
|
|
||||||
menuUtils.fetchAndPopulateDropdowns(node.configUrls, elements, node); // function for all assets
|
|
||||||
menuUtils.initBasicToggles(elements);
|
|
||||||
|
|
||||||
})
|
|
||||||
}catch(e){
|
|
||||||
console.log("Error fetching project settings", e);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(node.d){
|
|
||||||
//this means node is disabled
|
|
||||||
console.log("Current status of node is disabled");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
},
|
},
|
||||||
|
|
||||||
oneditsave: function () {
|
oneditsave: function () {
|
||||||
const node = this;
|
const node = this;
|
||||||
|
|
||||||
@@ -129,7 +59,7 @@
|
|||||||
console.log(`${node.uuid}`);
|
console.log(`${node.uuid}`);
|
||||||
|
|
||||||
// Save basic properties
|
// Save basic properties
|
||||||
["name", "supplier", "subType", "model", "unit", "smooth_method"].forEach(
|
["name", "supplier", "category", "assetType", "model", "unit", "smooth_method"].forEach(
|
||||||
(field) => (node[field] = document.getElementById(`node-input-${field}`).value || "")
|
(field) => (node[field] = document.getElementById(`node-input-${field}`).value || "")
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -153,30 +83,14 @@
|
|||||||
RED.notify("Unit selection is required.", "error");
|
RED.notify("Unit selection is required.", "error");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (node.subType && !node.unit) {
|
// Validation checks - FIXED
|
||||||
RED.notify("Unit must be set when specifying a subtype.", "error");
|
if (node.assetType && !node.unit) {
|
||||||
|
RED.notify("Unit must be set when specifying a type.", "error");
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log("stored node modelData", node.modelMetadata);
|
console.log("stored node modelData", node.modelMetadata);
|
||||||
console.log("------------ Changes saved to measurement node preparing to save to API ------------");
|
console.log("------------ Changes saved to measurement node preparing to save to API ------------");
|
||||||
|
|
||||||
try{
|
|
||||||
// Fetch project settings
|
|
||||||
menuUtils.apiCall(node,node.configUrls)
|
|
||||||
.then((response) => {
|
|
||||||
|
|
||||||
//save response to node information
|
|
||||||
node.assetTagCode = response.asset_tag_number;
|
|
||||||
|
|
||||||
})
|
|
||||||
.catch((error) => {
|
|
||||||
console.log("Error during API call", error);
|
|
||||||
});
|
|
||||||
|
|
||||||
}catch(e){
|
|
||||||
console.log("Error saving assetID and tagnumber", e);
|
|
||||||
}
|
|
||||||
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
@@ -256,7 +170,6 @@
|
|||||||
<label for="node-input-smooth_method"
|
<label for="node-input-smooth_method"
|
||||||
><i class="fa fa-line-chart"></i> Smoothing</label>
|
><i class="fa fa-line-chart"></i> Smoothing</label>
|
||||||
<select id="node-input-smooth_method" style="width:60%;">
|
<select id="node-input-smooth_method" style="width:60%;">
|
||||||
<!-- Filled dynamically from measurementConfig.json or fallback -->
|
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -272,31 +185,27 @@
|
|||||||
<div class="form-tips">Number of samples for smoothing</div>
|
<div class="form-tips">Number of samples for smoothing</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Optional Extended Fields: supplier, type, subType, model -->
|
<!-- Optional Extended Fields: supplier, cat, type, model, unit -->
|
||||||
<hr />
|
<hr />
|
||||||
<div class="form-row">
|
<div class="form-row">
|
||||||
<label for="node-input-supplier"
|
<label for="node-input-supplier"><i class="fa fa-industry"></i> Supplier</label>
|
||||||
><i class="fa fa-industry"></i> Supplier</label>
|
<select id="node-input-supplier" style="width:70%;"></select>
|
||||||
<select id="node-input-supplier" style="width:60%;">
|
|
||||||
<option value="">(optional)</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="form-row">
|
<div class="form-row">
|
||||||
<label for="node-input-subType"
|
<label for="node-input-category"><i class="fa fa-sitemap"></i> Category</label>
|
||||||
><i class="fa fa-puzzle-piece"></i> SubType</label>
|
<select id="node-input-category" style="width:70%;"></select>
|
||||||
<select id="node-input-subType" style="width:60%;">
|
</div>
|
||||||
<option value="">(optional)</option>
|
<div class="form-row">
|
||||||
</select>
|
<label for="node-input-assetType"><i class="fa fa-puzzle-piece"></i> Type</label>
|
||||||
|
<select id="node-input-assetType" style="width:70%;"></select>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-row">
|
<div class="form-row">
|
||||||
<label for="node-input-model"><i class="fa fa-wrench"></i> Model</label>
|
<label for="node-input-model"><i class="fa fa-wrench"></i> Model</label>
|
||||||
<select id="node-input-model" style="width:60%;">
|
<select id="node-input-model" style="width:70%;"></select>
|
||||||
<option value="">(optional)</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="form-row">
|
<div class="form-row">
|
||||||
<label for="node-input-unit"><i class="fa fa-balance-scale"></i> Unit</label>
|
<label for="node-input-unit"><i class="fa fa-balance-scale"></i> Unit</label>
|
||||||
<select id="node-input-unit" style="width:60%;"></select>
|
<select id="node-input-unit" style="width:70%;"></select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<hr />
|
<hr />
|
||||||
|
|||||||
@@ -1,11 +1,10 @@
|
|||||||
console.log('Loading measurement.js module...');
|
console.log('Loading measurement.js module...');
|
||||||
// load helper modules from the generalFunctions folder
|
// load helper modules from the generalFunctions folder
|
||||||
const { outputUtils } = require('generalFunctions');
|
const { outputUtils, MenuManager } = require('generalFunctions');
|
||||||
|
|
||||||
//internal node-red node dependencies this is the class that will handle the measurement
|
//internal node-red node dependencies this is the class that will handle the measurement
|
||||||
const Measurement = require("./dependencies/measurement/measurement");
|
const Measurement = require("./dependencies/measurement/measurement");
|
||||||
const { menuUtils } = require('generalFunctions');
|
|
||||||
console.log('All dependencies loaded successfully');
|
console.log('All dependencies loaded successfully');
|
||||||
console.log(menuUtils);
|
|
||||||
|
|
||||||
module.exports = function (RED) {
|
module.exports = function (RED) {
|
||||||
function measurement(config) {
|
function measurement(config) {
|
||||||
@@ -151,9 +150,21 @@ module.exports = function (RED) {
|
|||||||
|
|
||||||
RED.nodes.registerType("measurement", measurement);
|
RED.nodes.registerType("measurement", measurement);
|
||||||
|
|
||||||
// Create a new instance of MenuUtils for use in the html browser
|
|
||||||
let menuUtil = new menuUtils();
|
const menuManager = new MenuManager();
|
||||||
// Create the endpoint with one line!
|
|
||||||
menuUtil.createMenuUtilsEndpoint(RED, 'measurement', menuUtils);
|
RED.httpAdmin.get("/measurement/menu.js", (req, res) => {
|
||||||
|
try {
|
||||||
|
const script = menuManager.createEndpoint('measurement', ['asset']);
|
||||||
|
res.set('Content-Type', 'application/javascript').send(script);
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error creating measurement menu script:", error);
|
||||||
|
res.status(500).send(`// Failed to generate menu data: ${error.message}`);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
console.log('Measurement node and its menu data endpoint are registered.');
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
Reference in New Issue
Block a user