Compare commits
2 Commits
66a48ea8b8
...
c6ab276c1e
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c6ab276c1e | ||
|
|
a98a241d5e |
@ -1,363 +0,0 @@
|
||||
// App Manager - Dynamic app loading with beautiful styling
|
||||
class AppManager {
|
||||
constructor() {
|
||||
this.cache = new Map();
|
||||
}
|
||||
|
||||
getRandomLoadingMessage() {
|
||||
const messages = [
|
||||
"Preparing your application settings...",
|
||||
"Gathering application information...",
|
||||
"Loading application configuration...",
|
||||
"Setting up your app management panel...",
|
||||
"Loading the perfect app settings...",
|
||||
"Crafting your application experience...",
|
||||
"Preparing your app control panel...",
|
||||
"Loading application details...",
|
||||
"Setting up your app workspace...",
|
||||
"Configuring your application environment..."
|
||||
];
|
||||
|
||||
return messages[Math.floor(Math.random() * messages.length)];
|
||||
}
|
||||
|
||||
async loadApp(appName) {
|
||||
//console.log(`AppManager: Loading ${appName} app...`);
|
||||
|
||||
// Check cache first
|
||||
if (this.cache.has(appName)) {
|
||||
//console.log(`AppManager: Using cached ${appName} app`);
|
||||
return this.cache.get(appName);
|
||||
}
|
||||
|
||||
try {
|
||||
// Load app data from apps.json
|
||||
const response = await fetch('/data/apps/generated/apps.json', { cache: 'no-store' });
|
||||
if (!response.ok) {
|
||||
throw new Error(`Failed to load apps.json: ${response.status}`);
|
||||
}
|
||||
|
||||
const appsData = await response.json();
|
||||
|
||||
// Try multiple ways to find the app
|
||||
let app = appsData.apps.find(app =>
|
||||
app.name.toLowerCase().includes(appName.toLowerCase()) ||
|
||||
app.command.toLowerCase().includes(appName.toLowerCase()) ||
|
||||
app.name === appName ||
|
||||
app.name.toLowerCase() === appName.toLowerCase()
|
||||
);
|
||||
|
||||
if (!app) {
|
||||
// Try case-insensitive exact match
|
||||
app = appsData.apps.find(app =>
|
||||
app.name.toLowerCase() === appName.toLowerCase() ||
|
||||
app.command.toLowerCase().includes(appName.toLowerCase())
|
||||
);
|
||||
}
|
||||
|
||||
if (!app) {
|
||||
//console.log(`Available apps:`, appsData.apps.map(a => ({ name: a.name, command: a.command })));
|
||||
throw new Error(`App ${appName} not found`);
|
||||
}
|
||||
|
||||
//console.log(`AppManager: Loaded ${appName} app:`, app);
|
||||
|
||||
// Cache the result
|
||||
this.cache.set(appName, app);
|
||||
|
||||
return app;
|
||||
} catch (error) {
|
||||
console.error(`AppManager: Error loading ${appName} app:`, error);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
async renderApp(appName) {
|
||||
//console.log(`AppManager: Rendering ${appName} app...`);
|
||||
|
||||
const configSection = document.getElementById('config-section');
|
||||
if (!configSection) {
|
||||
console.error('AppManager: config-section element not found');
|
||||
return;
|
||||
}
|
||||
|
||||
// Show loading with enhanced visual
|
||||
configSection.innerHTML = `
|
||||
<div class="loading-enhanced" style="padding: 22px;">
|
||||
<div class="loading-content" style="
|
||||
text-align: center;
|
||||
padding: 22px;
|
||||
background: var(--input-bg);
|
||||
border: 1px solid var(--border-color);
|
||||
border-radius: 6px;
|
||||
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
|
||||
">
|
||||
<div class="loading-spinner" style="
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
border: 3px solid rgba(52, 152, 219, 0.3);
|
||||
border-top: 3px solid #3498db;
|
||||
border-radius: 50%;
|
||||
animation: spin 1s linear infinite;
|
||||
margin: 0 auto 16px auto;
|
||||
display: inline-block;
|
||||
"></div>
|
||||
<div class="loading-message" style="
|
||||
font-size: 16px;
|
||||
color: var(--text-primary, #fff);
|
||||
font-weight: 500;
|
||||
margin-bottom: 8px;
|
||||
">
|
||||
Loading application...
|
||||
</div>
|
||||
<div class="loading-subtitle" style="
|
||||
font-size: 14px;
|
||||
color: var(--text-color, #fff);
|
||||
font-style: italic;
|
||||
">
|
||||
${this.getRandomLoadingMessage()}
|
||||
</div>
|
||||
</div>
|
||||
<style>
|
||||
@keyframes spin {
|
||||
0% { transform: rotate(0deg); }
|
||||
100% { transform: rotate(360deg); }
|
||||
}
|
||||
</style>
|
||||
</div>
|
||||
`;
|
||||
|
||||
// Update loading bar if available
|
||||
if (typeof router !== 'undefined' && router.updateProgress) {
|
||||
router.updateProgress(60);
|
||||
}
|
||||
|
||||
try {
|
||||
// Load app data
|
||||
const app = await this.loadApp(appName);
|
||||
|
||||
// Update loading bar
|
||||
if (typeof router !== 'undefined' && router.updateProgress) {
|
||||
router.updateProgress(70);
|
||||
}
|
||||
|
||||
if (!app) {
|
||||
configSection.innerHTML = '<div class="error">Application not found</div>';
|
||||
return;
|
||||
}
|
||||
|
||||
// App config comes from apps.json (window.apps), not a separate
|
||||
// per-app JSON. Pass null — the renderer's config section is gated
|
||||
// on appConfig?.config keys so it just skips that section.
|
||||
if (typeof router !== 'undefined' && router.updateProgress) {
|
||||
router.updateProgress(80);
|
||||
}
|
||||
|
||||
await this.renderWithOriginalStyling(appName, app, null);
|
||||
|
||||
// Final progress update
|
||||
if (typeof router !== 'undefined' && router.updateProgress) {
|
||||
router.updateProgress(80);
|
||||
}
|
||||
|
||||
//console.log(`AppManager: Successfully rendered ${appName} app`);
|
||||
|
||||
} catch (error) {
|
||||
console.error(`AppManager: Error rendering ${appName} app:`, error);
|
||||
configSection.innerHTML = `<div class="error">Failed to load ${appName} application: ${error.message}</div>`;
|
||||
}
|
||||
}
|
||||
|
||||
async renderWithOriginalStyling(appName, app, appConfig) {
|
||||
const configSection = document.getElementById('config-section');
|
||||
|
||||
// Render using the original app-config system
|
||||
let formHTML = `
|
||||
<div class="app-title">
|
||||
<h3>${app.displayName || app.name} Application</h3>
|
||||
<p>${app.description || 'Manage settings and configuration for ' + (app.displayName || app.name)}</p>
|
||||
</div>
|
||||
<div class="app-container">
|
||||
<form id="app-form-${appName}" class="app-form">
|
||||
`;
|
||||
|
||||
// App information section
|
||||
formHTML += `
|
||||
<div class="app-category">
|
||||
<h3>Application Information</h3>
|
||||
<p class="category-description">Basic information about this application</p>
|
||||
<div class="config-group">
|
||||
<div class="config-field">
|
||||
<label class="config-label">Application Name</label>
|
||||
<div class="config-input-wrapper">
|
||||
<input type="text" value="${app.displayName || app.name}" readonly class="config-input">
|
||||
</div>
|
||||
</div>
|
||||
<div class="config-field">
|
||||
<label class="config-label">Status</label>
|
||||
<div class="config-input-wrapper">
|
||||
<input type="text" value="${app.installed ? 'Installed' : 'Not Installed'}" readonly class="config-input">
|
||||
</div>
|
||||
</div>
|
||||
<div class="config-field">
|
||||
<label class="config-label">Version</label>
|
||||
<div class="config-input-wrapper">
|
||||
<input type="text" value="${app.version || 'N/A'}" readonly class="config-input">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
// Configuration section if available
|
||||
if (appConfig && appConfig.config && Object.keys(appConfig.config).length > 0) {
|
||||
// Use ConfigShared if available for beautiful rendering
|
||||
if (typeof ConfigShared !== 'undefined') {
|
||||
const groupedConfigs = ConfigShared.groupConfigKeys(appConfig.config);
|
||||
const categoryOrder = ConfigShared.extractCategoryOrder(appConfig.config);
|
||||
|
||||
for (const category of categoryOrder) {
|
||||
const keys = groupedConfigs[category];
|
||||
if (keys && keys.length > 0 && category !== 'Hidden/Unused Options') {
|
||||
const displayCategory = ConfigShared.formatCategoryName(category);
|
||||
const categoryDescription = await ConfigShared.getCategoryDescription(category);
|
||||
|
||||
formHTML += `
|
||||
<div class="config-category">
|
||||
<h3>${displayCategory}</h3>
|
||||
<p class="category-description">${categoryDescription}</p>
|
||||
<div class="config-group">
|
||||
${ConfigShared.generateFieldsForCategory(keys, category, appConfig.config, (fieldId, key, value, title, description, options, config) => ConfigShared.generateField(fieldId, key, value, title, description, options, config))}
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Fallback simple rendering
|
||||
formHTML += `
|
||||
<div class="config-category">
|
||||
<h3>Configuration</h3>
|
||||
<p class="category-description">Application-specific settings</p>
|
||||
<div class="config-group">
|
||||
<div class="config-field">
|
||||
<label class="config-label">Configuration Available</label>
|
||||
<div class="config-input-wrapper">
|
||||
<input type="text" value="Configuration loaded successfully" readonly class="config-input">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
} else {
|
||||
// No configuration available
|
||||
formHTML += `
|
||||
<div class="config-category">
|
||||
<h3>Configuration</h3>
|
||||
<p class="category-description">No specific configuration available for this application</p>
|
||||
<div class="config-group">
|
||||
<div class="config-field">
|
||||
<label class="config-label">Status</label>
|
||||
<div class="config-input-wrapper">
|
||||
<input type="text" value="No custom configuration needed" readonly class="config-input">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
formHTML += `
|
||||
</form>
|
||||
<div class="config-actions">
|
||||
<button type="button" class="btn btn-primary" onclick="AppManager.saveAppConfig('${appName}')">
|
||||
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||||
<path d="M19 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h11l5 5v11a2 2 0 0 1-2 2z"></path>
|
||||
<polyline points="17 21 17 13 7 13 7 21"></polyline>
|
||||
<polyline points="7 3 7 8 15 8"></polyline>
|
||||
</svg>
|
||||
Save Configuration
|
||||
</button>
|
||||
<button type="button" class="btn btn-secondary" onclick="AppManager.resetAppConfig('${appName}')">
|
||||
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||||
<polyline points="1 4 1 10 7 10"></polyline>
|
||||
<path d="M3.51 15a9 9 0 1 0 2.13-9.36L1 10"></path>
|
||||
</svg>
|
||||
Reset to Defaults
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
configSection.innerHTML = formHTML;
|
||||
}
|
||||
|
||||
static async saveAppConfig(appName) {
|
||||
//console.log(`AppManager: Saving ${appName} config...`);
|
||||
|
||||
const form = document.getElementById(`app-form-${appName}`);
|
||||
if (!form) {
|
||||
console.error('AppManager: Form not found');
|
||||
return;
|
||||
}
|
||||
|
||||
// Show success message
|
||||
if (typeof ConfigShared !== 'undefined' && ConfigShared.showNotification) {
|
||||
ConfigShared.showNotification('Application configuration saved successfully!', 'success');
|
||||
} else {
|
||||
// Fallback message
|
||||
const message = document.createElement('div');
|
||||
message.className = 'config-message success';
|
||||
message.textContent = 'Application configuration saved successfully!';
|
||||
|
||||
const actionsDiv = form.parentElement.querySelector('.config-actions');
|
||||
actionsDiv.insertBefore(message, actionsDiv.firstChild);
|
||||
|
||||
// Remove message after 3 seconds
|
||||
setTimeout(() => {
|
||||
if (message.parentNode) {
|
||||
message.parentNode.removeChild(message);
|
||||
}
|
||||
}, 3000);
|
||||
}
|
||||
}
|
||||
|
||||
static async resetAppConfig(appName) {
|
||||
//console.log(`AppManager: Resetting ${appName} config...`);
|
||||
|
||||
if (confirm('Are you sure you want to reset all settings to their default values?')) {
|
||||
// Reload the page to reset
|
||||
window.location.reload();
|
||||
}
|
||||
}
|
||||
|
||||
async loadScript(src) {
|
||||
// Check if script is already loaded
|
||||
const scriptId = src.replace(/[^a-zA-Z0-9]/g, '_');
|
||||
if (document.getElementById(scriptId)) {
|
||||
//console.log(`Script ${src} already loaded, skipping`);
|
||||
return;
|
||||
}
|
||||
|
||||
//console.log(`Loading script: ${src}`);
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
const script = document.createElement('script');
|
||||
script.src = src;
|
||||
script.id = scriptId;
|
||||
script.onload = () => {
|
||||
//console.log(`Script loaded successfully: ${src}`);
|
||||
resolve();
|
||||
};
|
||||
script.onerror = (error) => {
|
||||
console.error(`Script failed to load: ${src}`, error);
|
||||
reject(new Error(`Failed to load script: ${src}`));
|
||||
};
|
||||
document.head.appendChild(script);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Global instance
|
||||
window.appManager = new AppManager();
|
||||
@ -1,291 +0,0 @@
|
||||
// Configuration Router - Loads appropriate config component based on URL
|
||||
class ConfigRouter {
|
||||
constructor() {
|
||||
this.currentComponent = null;
|
||||
}
|
||||
|
||||
async init() {
|
||||
//console.log('ConfigRouter: Initializing...');
|
||||
// Get current category from query parameter or global variable
|
||||
const searchParams = new URLSearchParams(window.location.search);
|
||||
let currentCategory = searchParams.get('config') || window.configCategory || 'general';
|
||||
|
||||
//console.log(`Initial parsing - searchParams.get('config'): ${searchParams.get('config')}`);
|
||||
//console.log(`Window location search: ${window.location.search}`);
|
||||
//console.log(`Initial currentCategory: ${currentCategory}`);
|
||||
|
||||
// Handle the case where URL is config?=backup (malformed but common)
|
||||
// Check if we got the category from URL params, not from fallback
|
||||
const gotFromUrlParams = searchParams.get('config') !== null;
|
||||
|
||||
if (!gotFromUrlParams && window.location.search.includes('?=')) {
|
||||
//console.log(`URL contains ?= and no valid config param, attempting regex match...`);
|
||||
const pathMatch = window.location.search.match(/\?=([^&]+)/);
|
||||
//console.log(`Regex match result:`, pathMatch);
|
||||
//console.log(`Regex test result:`, /\?=([^&]+)/.test(window.location.search));
|
||||
if (pathMatch && pathMatch[1]) {
|
||||
currentCategory = pathMatch[1];
|
||||
//console.log(`Updated currentCategory from regex: ${currentCategory}`);
|
||||
} else {
|
||||
//console.log(`Regex failed to match, currentCategory remains: ${currentCategory}`);
|
||||
}
|
||||
} else {
|
||||
//console.log(`Got category from URL params (${gotFromUrlParams}) or URL doesn't contain ?=, keeping: ${currentCategory}`);
|
||||
}
|
||||
|
||||
//console.log(`Config router init: final category=${currentCategory}`);
|
||||
|
||||
// Backup config moved to /backup — redirect old URL/bookmarks.
|
||||
if (currentCategory === 'backup') {
|
||||
if (window.librePortalSPA && typeof window.librePortalSPA.navigate === 'function') {
|
||||
window.librePortalSPA.navigate('/backup', true);
|
||||
} else {
|
||||
window.location.href = '/backup';
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Load categories for sidebar
|
||||
await this.loadConfigCategories();
|
||||
|
||||
// Set active category in sidebar
|
||||
this.setActiveCategory(currentCategory);
|
||||
|
||||
// Load appropriate config component
|
||||
await this.loadConfigComponent(currentCategory);
|
||||
}
|
||||
|
||||
async loadConfigCategories() {
|
||||
try {
|
||||
//console.log('Loading config categories from: data/config/generated/configs.json');
|
||||
|
||||
// Start loading bar
|
||||
if (typeof router !== 'undefined' && router.updateProgress) {
|
||||
router.updateProgress(20);
|
||||
}
|
||||
|
||||
// Load unified config file
|
||||
const response = await fetch('/data/config/generated/configs.json');
|
||||
//console.log('Response status:', response.status, response.statusText);
|
||||
//console.log('Response ok:', response.ok);
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
|
||||
}
|
||||
|
||||
const text = await response.text();
|
||||
//console.log('Raw response text:', text);
|
||||
//console.log('Text length:', text.length);
|
||||
//console.log('First 100 chars:', text.substring(0, 100));
|
||||
|
||||
if (!text || text.trim() === '') {
|
||||
throw new Error('Empty response from configs.json');
|
||||
}
|
||||
|
||||
const data = JSON.parse(text);
|
||||
const categories = data.categories;
|
||||
|
||||
//console.log('Parsed categories:', categories);
|
||||
|
||||
if (typeof router !== 'undefined' && router.updateProgress) {
|
||||
router.updateProgress(60);
|
||||
}
|
||||
|
||||
const categoriesList = document.getElementById('config-categories-list');
|
||||
if (!categoriesList) {
|
||||
console.error('config-categories-list element not found');
|
||||
return;
|
||||
}
|
||||
|
||||
categoriesList.innerHTML = '';
|
||||
|
||||
// Convert categories object to array and sort by ORDER
|
||||
const categoriesArray = Object.entries(categories).map(([key, value]) => ({
|
||||
id: key,
|
||||
...value
|
||||
}));
|
||||
|
||||
// Sort by ORDER if available, otherwise by title
|
||||
categoriesArray.sort((a, b) => {
|
||||
const orderA = parseInt(a.order) || 999;
|
||||
const orderB = parseInt(b.order) || 999;
|
||||
return orderA - orderB;
|
||||
});
|
||||
|
||||
categoriesArray.forEach(category => {
|
||||
const categoryItem = document.createElement('div');
|
||||
categoryItem.className = 'category';
|
||||
categoryItem.setAttribute('data-category', category.id);
|
||||
|
||||
// Use correct icon from our new structure
|
||||
const iconName = category.icon || category.id;
|
||||
const iconPath = `/icons/config/${iconName}.svg`;
|
||||
//console.log(`Category: ${category.id}, Icon path: ${iconPath}`);
|
||||
categoryItem.innerHTML = `
|
||||
<img src="${iconPath}" alt="${category.title}" style="width: 20px; height: 20px; margin-right: 8px;"/>
|
||||
${category.title}
|
||||
`;
|
||||
|
||||
categoryItem.addEventListener('click', () => {
|
||||
//console.log(`Category clicked: ${category.id}`);
|
||||
this.navigateToCategory(category.id);
|
||||
});
|
||||
|
||||
categoriesList.appendChild(categoryItem);
|
||||
});
|
||||
|
||||
if (typeof router !== 'undefined' && router.updateProgress) {
|
||||
router.updateProgress(80);
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
console.error('Error loading config categories:', error);
|
||||
if (typeof router !== 'undefined' && router.hideLoadingBar) {
|
||||
router.hideLoadingBar();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
setActiveCategory(categoryId) {
|
||||
// Update active state
|
||||
document.querySelectorAll('.category').forEach(item => {
|
||||
item.classList.remove('active');
|
||||
});
|
||||
document.querySelector(`[data-category="${categoryId}"]`)?.classList.add('active');
|
||||
}
|
||||
|
||||
navigateToCategory(categoryId) {
|
||||
//console.log(`Config router: navigating to ${categoryId} (SPA mode)`);
|
||||
|
||||
// Update URL without full page reload using query parameter
|
||||
const url = `/config?=${categoryId}`;
|
||||
//console.log(`Updating URL to: ${url}`);
|
||||
window.history.pushState({}, '', url);
|
||||
|
||||
// Set active category
|
||||
this.setActiveCategory(categoryId);
|
||||
|
||||
// Load config content dynamically
|
||||
this.loadConfigComponent(categoryId);
|
||||
}
|
||||
|
||||
async loadConfigComponent(categoryId) {
|
||||
try {
|
||||
//console.log(`Config router: Loading component for ${categoryId}`);
|
||||
|
||||
// Start loading bar
|
||||
if (typeof router !== 'undefined' && router.updateProgress) {
|
||||
router.updateProgress(10);
|
||||
router.showLoadingBar();
|
||||
}
|
||||
|
||||
// Clear current content
|
||||
const configSection = document.getElementById('config-section');
|
||||
if (configSection) {
|
||||
configSection.innerHTML = '<div class="loading">Loading configuration...</div>';
|
||||
}
|
||||
|
||||
// Update progress
|
||||
if (typeof router !== 'undefined' && router.updateProgress) {
|
||||
router.updateProgress(30);
|
||||
}
|
||||
|
||||
// Use the simple config manager
|
||||
if (window.configManager) {
|
||||
//console.log(`Using ConfigManager for ${categoryId}`);
|
||||
if (typeof router !== 'undefined' && router.updateProgress) {
|
||||
router.updateProgress(50);
|
||||
}
|
||||
|
||||
await window.configManager.renderConfig(categoryId);
|
||||
|
||||
if (typeof router !== 'undefined' && router.updateProgress) {
|
||||
router.updateProgress(90);
|
||||
}
|
||||
} else {
|
||||
// Fallback - try to load config manager
|
||||
//console.log('ConfigManager not available, loading it...');
|
||||
if (typeof router !== 'undefined' && router.updateProgress) {
|
||||
router.updateProgress(40);
|
||||
}
|
||||
|
||||
await new Promise((resolve) => {
|
||||
const script = document.createElement('script');
|
||||
script.src = '/js/components/config/config-manager.js';
|
||||
script.onload = async () => {
|
||||
if (window.configManager) {
|
||||
if (typeof router !== 'undefined' && router.updateProgress) {
|
||||
router.updateProgress(60);
|
||||
}
|
||||
await window.configManager.renderConfig(categoryId);
|
||||
if (typeof router !== 'undefined' && router.updateProgress) {
|
||||
router.updateProgress(90);
|
||||
}
|
||||
}
|
||||
resolve();
|
||||
};
|
||||
document.head.appendChild(script);
|
||||
});
|
||||
}
|
||||
|
||||
// Complete loading
|
||||
if (typeof router !== 'undefined' && router.updateProgress) {
|
||||
router.updateProgress(100);
|
||||
setTimeout(() => {
|
||||
router.hideLoadingBar();
|
||||
}, 500); // Small delay to show completion
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
console.error(`Error loading config component for ${categoryId}:`, error);
|
||||
const configSection = document.getElementById('config-section');
|
||||
if (configSection) {
|
||||
configSection.innerHTML = `<div class="error">Failed to load ${categoryId} configuration: ${error.message}</div>`;
|
||||
}
|
||||
if (typeof router !== 'undefined' && router.hideLoadingBar) {
|
||||
router.hideLoadingBar();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async loadConfigComponentManual(categoryId) {
|
||||
const configSection = document.getElementById('config-section');
|
||||
|
||||
// This method is no longer needed since we use ConfigManager for all categories
|
||||
// The individual config classes have been removed
|
||||
//console.log(`ConfigRouter: loadConfigComponentManual called for ${categoryId} - delegating to ConfigManager`);
|
||||
|
||||
// Use ConfigManager for all categories now
|
||||
if (window.configManager) {
|
||||
await window.configManager.renderConfig(categoryId);
|
||||
} else {
|
||||
configSection.innerHTML = '<div class="error">ConfigManager not available</div>';
|
||||
}
|
||||
|
||||
// Hide loading bar
|
||||
if (typeof router !== 'undefined' && router.hideLoadingBar) {
|
||||
router.hideLoadingBar();
|
||||
}
|
||||
}
|
||||
|
||||
async loadScript(src) {
|
||||
// Check if script is already loaded
|
||||
const scriptId = src.replace(/[^a-zA-Z0-9]/g, '_');
|
||||
if (document.getElementById(scriptId)) {
|
||||
//console.log(`Script ${src} already loaded, skipping`);
|
||||
return;
|
||||
}
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
const script = document.createElement('script');
|
||||
script.src = src;
|
||||
script.id = scriptId;
|
||||
script.onload = resolve;
|
||||
script.onerror = reject;
|
||||
document.head.appendChild(script);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Export for global access
|
||||
window.ConfigRouter = ConfigRouter;
|
||||
Loading…
x
Reference in New Issue
Block a user