Add pending apps and frontend components
- apps/captain-mobile: Mobile API service - apps/flow-ui: Flow UI application - apps/mindlink: Mindlink application - apps/storage: Storage API and workers - apps/tzzr-cli: TZZR CLI tool - deck-frontend/backups: Historical TypeScript versions - hst-frontend: Standalone HST frontend Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
174
deck-frontend/backups/20260113_212146/src/modules/loader.ts
Normal file
174
deck-frontend/backups/20260113_212146/src/modules/loader.ts
Normal file
@@ -0,0 +1,174 @@
|
||||
/**
|
||||
* ModuleLoader - Carga dinámica de módulos
|
||||
*
|
||||
* Responsabilidades:
|
||||
* - Cargar el módulo correcto según la base
|
||||
* - Manejar cache de módulos
|
||||
* - Gestionar lifecycle (mount/unmount)
|
||||
*/
|
||||
|
||||
import { BaseModule, type ModuleContext } from './registry.ts';
|
||||
import { getModuleConfig, isModuleEnabled } from './configs/index.ts';
|
||||
import { StandardModule } from './standard/index.ts';
|
||||
import type { Store } from '@/state/store.ts';
|
||||
import type { AppState, BaseType } from '@/types/index.ts';
|
||||
|
||||
export interface LoaderTargets {
|
||||
container: HTMLElement;
|
||||
leftPanel: HTMLElement;
|
||||
groupsBar: HTMLElement;
|
||||
showDetail: (mrf: string) => void;
|
||||
}
|
||||
|
||||
export class ModuleLoader {
|
||||
private store: Store<AppState>;
|
||||
private currentModule: BaseModule | null = null;
|
||||
private currentBase: BaseType | null = null;
|
||||
|
||||
constructor(store: Store<AppState>) {
|
||||
this.store = store;
|
||||
}
|
||||
|
||||
/**
|
||||
* Cargar módulo para una base
|
||||
*/
|
||||
async load(base: BaseType, targets: LoaderTargets): Promise<void> {
|
||||
const config = getModuleConfig(base);
|
||||
|
||||
// Verificar si el módulo está habilitado
|
||||
if (!isModuleEnabled(base)) {
|
||||
this.showDisabledMessage(targets.container, config.name);
|
||||
targets.leftPanel.innerHTML = '';
|
||||
targets.groupsBar.innerHTML = '';
|
||||
return;
|
||||
}
|
||||
|
||||
// Si ya está cargado el mismo módulo, solo re-renderizar
|
||||
if (this.currentBase === base && this.currentModule) {
|
||||
this.currentModule.render();
|
||||
return;
|
||||
}
|
||||
|
||||
// Unmount módulo actual
|
||||
this.currentModule?.unmount();
|
||||
this.currentModule = null;
|
||||
this.currentBase = null;
|
||||
|
||||
// Show loading
|
||||
targets.container.innerHTML = '<div class="loading">Cargando...</div>';
|
||||
|
||||
// Crear contexto
|
||||
const ctx: ModuleContext = {
|
||||
container: targets.container,
|
||||
leftPanel: targets.leftPanel,
|
||||
groupsBar: targets.groupsBar,
|
||||
store: this.store,
|
||||
config,
|
||||
showDetail: targets.showDetail
|
||||
};
|
||||
|
||||
// Crear módulo según tipo
|
||||
let module: BaseModule;
|
||||
|
||||
switch (config.renderType) {
|
||||
case 'standard':
|
||||
module = new StandardModule(ctx);
|
||||
break;
|
||||
|
||||
case 'chat':
|
||||
case 'custom':
|
||||
// Carga dinámica de módulos custom
|
||||
if (config.customModule) {
|
||||
try {
|
||||
const { default: CustomModule } = await config.customModule();
|
||||
module = new CustomModule(ctx);
|
||||
} catch (error) {
|
||||
console.error(`Failed to load custom module for ${base}:`, error);
|
||||
this.showErrorMessage(targets.container, `Error cargando módulo ${config.name}`);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
this.showDisabledMessage(targets.container, config.name);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
console.error(`Unknown render type: ${config.renderType}`);
|
||||
this.showErrorMessage(targets.container, 'Tipo de módulo desconocido');
|
||||
return;
|
||||
}
|
||||
|
||||
// Mount módulo
|
||||
try {
|
||||
await module.mount();
|
||||
this.currentModule = module;
|
||||
this.currentBase = base;
|
||||
} catch (error) {
|
||||
console.error(`Failed to mount module for ${base}:`, error);
|
||||
this.showErrorMessage(targets.container, `Error inicializando ${config.name}`);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Re-renderizar módulo actual (ej: cuando cambia la vista)
|
||||
*/
|
||||
rerender(): void {
|
||||
if (this.currentModule) {
|
||||
this.currentModule.render();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Re-renderizar sidebar del módulo actual
|
||||
*/
|
||||
rerenderSidebar(): void {
|
||||
if (this.currentModule) {
|
||||
this.currentModule.renderSidebar();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtener módulo actual
|
||||
*/
|
||||
getCurrentModule(): BaseModule | null {
|
||||
return this.currentModule;
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtener base actual
|
||||
*/
|
||||
getCurrentBase(): BaseType | null {
|
||||
return this.currentBase;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unmount módulo actual
|
||||
*/
|
||||
unmount(): void {
|
||||
this.currentModule?.unmount();
|
||||
this.currentModule = null;
|
||||
this.currentBase = null;
|
||||
}
|
||||
|
||||
private showDisabledMessage(container: HTMLElement, moduleName: string): void {
|
||||
container.innerHTML = `
|
||||
<div class="module-disabled">
|
||||
<div class="module-disabled-icon">🚧</div>
|
||||
<div class="module-disabled-title">${moduleName}</div>
|
||||
<div class="module-disabled-text">Próximamente</div>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
private showErrorMessage(container: HTMLElement, message: string): void {
|
||||
container.innerHTML = `
|
||||
<div class="module-error">
|
||||
<div class="module-error-icon">⚠️</div>
|
||||
<div class="module-error-text">${message}</div>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
}
|
||||
|
||||
export default ModuleLoader;
|
||||
Reference in New Issue
Block a user