license update and enhancements to measurement functionality + child parent relationship
This commit is contained in:
@@ -1,23 +1,26 @@
|
||||
const AssetMenu = require('./asset.js');
|
||||
const { TagcodeApp, DynamicAssetMenu } = require('./tagcodeApp.js');
|
||||
const LoggerMenu = require('./logger.js');
|
||||
const PhysicalPositionMenu = require('./physicalPosition.js');
|
||||
|
||||
class MenuManager {
|
||||
|
||||
constructor() {
|
||||
this.registeredMenus = new Map(); // Store menu type instances
|
||||
this.registerMenu('asset', new AssetMenu()); // Register asset menu by default
|
||||
this.registerMenu('logger', new LoggerMenu()); // Register logger menu by default
|
||||
this.registerMenu('position', new PhysicalPositionMenu()); // Register position menu by default
|
||||
this.registeredMenus = new Map();
|
||||
// Register factory functions
|
||||
this.registerMenu('asset', () => new AssetMenu()); // static menu to be replaced by dynamic one but later
|
||||
//this.registerMenu('asset', (nodeName) => new DynamicAssetMenu(nodeName, new TagcodeApp()));
|
||||
this.registerMenu('logger', () => new LoggerMenu());
|
||||
this.registerMenu('position', () => new PhysicalPositionMenu());
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a menu type with its handler instance
|
||||
* Register a menu type with its handler factory function
|
||||
* @param {string} menuType - The type of menu (e.g., 'asset', 'logging')
|
||||
* @param {object} menuHandler - The menu handler instance
|
||||
* @param {function} menuFactory - The menu factory function
|
||||
*/
|
||||
registerMenu(menuType, menuHandler) {
|
||||
this.registeredMenus.set(menuType, menuHandler);
|
||||
registerMenu(menuType, menuFactory) {
|
||||
this.registeredMenus.set(menuType, menuFactory);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -27,58 +30,145 @@ class MenuManager {
|
||||
* @returns {string} Complete JavaScript code to serve
|
||||
*/
|
||||
createEndpoint(nodeName, menuTypes) {
|
||||
// 1. Collect all menu data
|
||||
const menuData = {};
|
||||
menuTypes.forEach(menuType => {
|
||||
const handler = this.registeredMenus.get(menuType);
|
||||
if (handler && typeof handler.getAllMenuData === 'function') {
|
||||
menuData[menuType] = handler.getAllMenuData();
|
||||
try {
|
||||
// ✅ Create instances using factory functions with proper error handling
|
||||
const instantiatedMenus = new Map();
|
||||
|
||||
menuTypes.forEach(menuType => {
|
||||
try {
|
||||
const factory = this.registeredMenus.get(menuType);
|
||||
if (typeof factory === 'function') {
|
||||
const instance = factory(nodeName);
|
||||
instantiatedMenus.set(menuType, instance);
|
||||
} else {
|
||||
console.warn(`No factory function found for menu type: ${menuType}`);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(`Error creating instance for ${menuType}:`, error);
|
||||
}
|
||||
});
|
||||
|
||||
// ✅ Collect all menu data with error handling
|
||||
const menuData = {};
|
||||
menuTypes.forEach(menuType => {
|
||||
try {
|
||||
const handler = instantiatedMenus.get(menuType);
|
||||
if (handler && typeof handler.getAllMenuData === 'function') {
|
||||
menuData[menuType] = handler.getAllMenuData();
|
||||
} else {
|
||||
// Provide default empty data if method doesn't exist
|
||||
menuData[menuType] = {};
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(`Error getting menu data for ${menuType}:`, error);
|
||||
menuData[menuType] = {};
|
||||
}
|
||||
});
|
||||
|
||||
// ✅ Generate HTML injection code with error handling
|
||||
const htmlInjections = menuTypes.map(type => {
|
||||
try {
|
||||
const menu = instantiatedMenus.get(type);
|
||||
if (menu && typeof menu.getHtmlInjectionCode === 'function') {
|
||||
return menu.getHtmlInjectionCode(nodeName);
|
||||
}
|
||||
return '';
|
||||
} catch (error) {
|
||||
console.error(`Error generating HTML injection for ${type}:`, error);
|
||||
return `// Error generating HTML injection for ${type}: ${error.message}`;
|
||||
}
|
||||
}).join('\n');
|
||||
|
||||
// ✅ Collect all client initialization code with error handling
|
||||
const initFunctions = [];
|
||||
menuTypes.forEach(menuType => {
|
||||
try {
|
||||
const handler = instantiatedMenus.get(menuType);
|
||||
if (handler && typeof handler.getClientInitCode === 'function') {
|
||||
initFunctions.push(handler.getClientInitCode(nodeName));
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(`Error generating init code for ${menuType}:`, error);
|
||||
initFunctions.push(`// Error in ${menuType} initialization: ${error.message}`);
|
||||
}
|
||||
});
|
||||
|
||||
// Convert menu data to JSON
|
||||
const menuDataJSON = JSON.stringify(menuData, null, 2);
|
||||
|
||||
// ✅ Assemble the complete script with comprehensive error handling
|
||||
return `
|
||||
try {
|
||||
// Create the namespace structure with safety checks
|
||||
window.EVOLV = window.EVOLV || {};
|
||||
window.EVOLV.nodes = window.EVOLV.nodes || {};
|
||||
window.EVOLV.nodes.${nodeName} = window.EVOLV.nodes.${nodeName} || {};
|
||||
|
||||
// Initialize menu namespaces
|
||||
${menuTypes.map(type => `window.EVOLV.nodes.${nodeName}.${type}Menu = window.EVOLV.nodes.${nodeName}.${type}Menu || {};`).join('\n ')}
|
||||
|
||||
// Inject the pre-loaded menu data directly into the namespace
|
||||
window.EVOLV.nodes.${nodeName}.menuData = ${menuDataJSON};
|
||||
|
||||
// HTML injections with error handling
|
||||
try {
|
||||
${htmlInjections}
|
||||
} catch (htmlError) {
|
||||
console.error('Error in HTML injections for ${nodeName}:', htmlError);
|
||||
}
|
||||
|
||||
// Initialize functions with error handling
|
||||
try {
|
||||
${initFunctions.join('\n\n ')}
|
||||
} catch (initError) {
|
||||
console.error('Error in initialization functions for ${nodeName}:', initError);
|
||||
}
|
||||
|
||||
// Main initialization function that calls all menu initializers
|
||||
window.EVOLV.nodes.${nodeName}.initEditor = function(node) {
|
||||
try {
|
||||
${menuTypes.map(type => `
|
||||
try {
|
||||
if (window.EVOLV.nodes.${nodeName}.${type}Menu && window.EVOLV.nodes.${nodeName}.${type}Menu.initEditor) {
|
||||
window.EVOLV.nodes.${nodeName}.${type}Menu.initEditor(node);
|
||||
}
|
||||
} catch (${type}Error) {
|
||||
console.error('Error initializing ${type} menu for ${nodeName}:', ${type}Error);
|
||||
}`).join('')}
|
||||
} catch (editorError) {
|
||||
console.error('Error in main editor initialization for ${nodeName}:', editorError);
|
||||
}
|
||||
};
|
||||
|
||||
console.log('${nodeName} menu data and initializers loaded for: ${menuTypes.join(', ')}');
|
||||
|
||||
} catch (globalError) {
|
||||
console.error('Critical error in ${nodeName} menu initialization:', globalError);
|
||||
|
||||
// Fallback initialization
|
||||
window.EVOLV = window.EVOLV || {};
|
||||
window.EVOLV.nodes = window.EVOLV.nodes || {};
|
||||
window.EVOLV.nodes.${nodeName} = window.EVOLV.nodes.${nodeName} || {};
|
||||
window.EVOLV.nodes.${nodeName}.initEditor = function(node) {
|
||||
console.warn('Using fallback editor initialization for ${nodeName}');
|
||||
};
|
||||
}
|
||||
});
|
||||
`;
|
||||
|
||||
// Generate HTML injection code
|
||||
const htmlInjections = menuTypes.map(type => {
|
||||
const menu = this.registeredMenus.get(type);
|
||||
if (menu && menu.getHtmlInjectionCode) {
|
||||
return menu.getHtmlInjectionCode(nodeName);
|
||||
}
|
||||
return '';
|
||||
}).join('\n');
|
||||
|
||||
// 2. Collect all client initialization code
|
||||
const initFunctions = [];
|
||||
menuTypes.forEach(menuType => {
|
||||
const handler = this.registeredMenus.get(menuType);
|
||||
if (handler && typeof handler.getClientInitCode === 'function') {
|
||||
initFunctions.push(handler.getClientInitCode(nodeName));
|
||||
}
|
||||
});
|
||||
|
||||
// 3. Convert menu data to JSON
|
||||
const menuDataJSON = JSON.stringify(menuData, null, 2);
|
||||
|
||||
// 4. Assemble the complete script
|
||||
return `
|
||||
// Create the namespace structure
|
||||
window.EVOLV = window.EVOLV || {};
|
||||
window.EVOLV.nodes = window.EVOLV.nodes || {};
|
||||
window.EVOLV.nodes.${nodeName} = window.EVOLV.nodes.${nodeName} || {};
|
||||
|
||||
// Inject the pre-loaded menu data directly into the namespace
|
||||
window.EVOLV.nodes.${nodeName}.menuData = ${menuDataJSON};
|
||||
|
||||
${initFunctions.join('\n\n')}
|
||||
|
||||
// Main initialization function that calls all menu initializers
|
||||
window.EVOLV.nodes.${nodeName}.initEditor = function(node) {
|
||||
${menuTypes.map(type => `
|
||||
if (window.EVOLV.nodes.${nodeName}.${type}Menu && window.EVOLV.nodes.${nodeName}.${type}Menu.initEditor) {
|
||||
window.EVOLV.nodes.${nodeName}.${type}Menu.initEditor(node);
|
||||
}`).join('')}
|
||||
};
|
||||
|
||||
console.log('${nodeName} menu data and initializers loaded for: ${menuTypes.join(', ')}');
|
||||
`;
|
||||
} catch (error) {
|
||||
console.error(`Critical error creating endpoint for ${nodeName}:`, error);
|
||||
|
||||
// Return minimal fallback script
|
||||
return `
|
||||
window.EVOLV = window.EVOLV || {};
|
||||
window.EVOLV.nodes = window.EVOLV.nodes || {};
|
||||
window.EVOLV.nodes.${nodeName} = window.EVOLV.nodes.${nodeName} || {};
|
||||
window.EVOLV.nodes.${nodeName}.initEditor = function(node) {
|
||||
console.error('Menu system failed to initialize for ${nodeName}');
|
||||
};
|
||||
console.error('Menu system failed for ${nodeName}:', '${error.message}');
|
||||
`;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user