Overview
The Templates module (Plantillas) is a powerful system for creating, managing, and sharing reusable message templates. It features real-time collaboration, color coding, favorites management, and intelligent caching for optimal performance.
User Guide See the complete guide for step-by-step instructions on working with templates
Key Features
Real-time Collaboration Changes sync instantly across all users via Firebase
Color Organization Assign colors to templates for visual categorization
Smart Caching 5-minute cache reduces Firebase reads and improves performance
Favorites System Quick access to frequently used templates
Search & Filter Search by title or content with real-time filtering
Export to Excel Batch export templates for offline use
Template Structure
Each template in the system has the following structure:
{
titulo : "Template Title" ,
contenido : "<p>HTML content of the template</p>" ,
asesor : "Nombre_del_Creador" ,
timestamp : 1234567890 ,
color : "azul" // Optional color code
}
Color System
Templates support 8 predefined colors:
const COLORES_DISPONIBLES = {
'azul' : '#3b82f6' ,
'verde' : '#10b981' ,
'rojo' : '#ef4444' ,
'morado' : '#a855f7' ,
'amarillo' : '#f59e0b' ,
'rosa' : '#ec4899' ,
'cyan' : '#06b6d4' ,
'naranja' : '#f97316'
};
Caching Strategy
The Templates module implements a sophisticated caching system to optimize performance:
LocalStorage Cache
let plantillasCache = JSON . parse ( localStorage . getItem ( 'plantillasCache' )) || null ;
let favoritosCache = JSON . parse ( localStorage . getItem ( 'favoritosCache' )) || null ;
let coloresCache = JSON . parse ( localStorage . getItem ( 'coloresPlantillas' )) || {};
let lastUpdate = localStorage . getItem ( 'plantillasLastUpdate' ) || 0 ;
const now = Date . now ();
const cacheValid = plantillasCache && favoritosCache && ( now - lastUpdate < 300000 ); // 5 minutes
if ( cacheValid ) {
renderizarPlantillas ( plantillasCache , favoritosCache , asesorActual );
verificarCambiosEnSegundoPlano ( asesorActual );
} else {
cargarPlantillasCompleto ( asesorActual , loadingScreen );
}
Background Verification
Even when using cached data, the system checks for updates in the background:
function verificarCambiosEnSegundoPlano ( asesorActual ) {
Promise . all ([
firebase . database (). ref ( 'Plantillas' ). once ( 'value' ),
firebase . database (). ref ( `Preferencias/ ${ asesorActual } /Favoritos` ). once ( 'value' )
]). then (([ plantillasSnap , favSnap ]) => {
const plantillasNuevas = plantillasSnap . val () || {};
const favoritosNuevos = favSnap . val () || {};
// Compare and update if changes detected
if ( JSON . stringify ( plantillasNuevas ) !== JSON . stringify ( plantillasCache )) {
actualizarCache ( plantillasNuevas , favoritosNuevos );
renderizarPlantillas ( plantillasNuevas , favoritosNuevos , asesorActual );
}
});
}
The 5-minute cache significantly reduces Firebase read operations while ensuring data freshness through background synchronization.
Template Operations
Creating Templates
Open creation modal
Click the Nueva Plantilla button to open the creation dialog.
Enter template details
Provide a unique title and HTML content. The system validates title uniqueness in real-time. tituloInput . addEventListener ( 'input' , function () {
const titulo = this . value . trim ();
if ( plantillasExistentes [ titulo ]) {
// Show error: title already exists
guardarBtn . disabled = true ;
} else {
guardarBtn . disabled = false ;
}
});
Assign color (optional)
Select a color from the available palette to categorize your template.
Save to Firebase
Templates are saved with automatic timestamp and creator attribution. const plantillaData = {
titulo: titulo ,
contenido: contenido ,
asesor: asesorActual ,
timestamp: Date . now (),
color: colorSeleccionado || null
};
firebase . database (). ref ( `Plantillas/ ${ titulo } ` ). set ( plantillaData );
Using Templates
When you click a template, it’s automatically copied to your clipboard with time-based greeting:
function copiarPlantilla ( contenido ) {
const hora = new Date (). getHours ();
let saludo ;
if ( hora >= 5 && hora < 12 ) {
saludo = "Buenos días" ;
} else if ( hora >= 12 && hora < 19 ) {
saludo = "Buenas tardes" ;
} else {
saludo = "Buenas noches" ;
}
const textoConSaludo = ` ${ saludo } \n\n ${ contenido } ` ;
navigator . clipboard . writeText ( textoConSaludo );
// Optional: Auto-clear clipboard after timer
if ( timerSwitch . checked ) {
setTimeout (() => {
navigator . clipboard . writeText ( '' );
}, 8000 );
}
}
Favorites System
The favorites feature allows quick access to frequently used templates:
Adding to Favorites
function toggleFavorito ( titulo , asesorActual ) {
const favRef = firebase . database (). ref ( `Preferencias/ ${ asesorActual } /Favoritos/ ${ titulo } ` );
favRef . once ( 'value' ). then ( snapshot => {
if ( snapshot . exists ()) {
// Remove from favorites
favRef . remove ();
} else {
// Add to favorites
favRef . set ( true );
}
});
}
Favorites Display
Favorites are displayed at the top of the template list:
Star icon : Filled for favorites, outlined for non-favorites
Sort order : Favorites appear first, then by timestamp
User-specific : Each user has their own favorites list
Favorites sync across devices via Firebase, so your preferred templates are available wherever you log in.
Search Functionality
The search system supports both title and content searching:
function buscarPlantillas () {
const query = searchInput . value . toLowerCase ();
const plantillas = document . querySelectorAll ( '.plantilla-card' );
plantillas . forEach ( card => {
const titulo = card . dataset . titulo . toLowerCase ();
const contenido = card . dataset . contenido . toLowerCase ();
if ( titulo . includes ( query ) || contenido . includes ( query )) {
card . style . display = 'block' ;
} else {
card . style . display = 'none' ;
}
});
}
Search Features
Real-time filtering : Results update as you type
Multi-field search : Searches both title and content
Case-insensitive : Matches regardless of capitalization
Highlight matches : Search terms are highlighted in results
Export Functionality
Export all templates to Excel format for backup or offline use:
function exportarTodasPlantillas () {
const plantillas = [];
Object . entries ( plantillasCache ). forEach (([ titulo , data ]) => {
plantillas . push ({
'Título' : titulo ,
'Contenido' : data . contenido . replace ( /< [ ^ > ] * >/ g , '' ), // Strip HTML
'Creador' : data . asesor ,
'Fecha' : new Date ( data . timestamp ). toLocaleString (),
'Color' : data . color || 'Sin color'
});
});
// Use TableExport library or similar
exportToExcel ( plantillas , 'plantillas.xlsx' );
}
Real-time Collaboration
The Templates module supports real-time updates across all connected users:
Firebase Listeners
firebase . database (). ref ( 'Plantillas' ). on ( 'child_added' , snapshot => {
const titulo = snapshot . key ;
const plantilla = snapshot . val ();
agregarPlantillaDOM ( titulo , plantilla );
});
firebase . database (). ref ( 'Plantillas' ). on ( 'child_changed' , snapshot => {
const titulo = snapshot . key ;
const plantilla = snapshot . val ();
actualizarPlantillaDOM ( titulo , plantilla );
});
firebase . database (). ref ( 'Plantillas' ). on ( 'child_removed' , snapshot => {
const titulo = snapshot . key ;
eliminarPlantillaDOM ( titulo );
});
Conflict Resolution
Last-write-wins strategy with timestamp tracking:
Each update includes a timestamp
Firebase atomic operations prevent race conditions
Users see a notification when templates are updated by others
Advanced Features
Current Duty Manager Display
The system shows which user is currently on duty:
firebase . database (). ref ( 'Almuerzo/Asesor' ). on ( 'value' , snapshot => {
const asesorAlmuerzo = snapshot . val ();
if ( asesorAlmuerzo ) {
document . getElementById ( 'asesorActual' ). textContent = asesorAlmuerzo ;
}
});
Auto-clear Clipboard Timer
Optional security feature to clear clipboard after copying:
var timerSwitch = document . getElementById ( 'timerSwitch' );
var timerPreference = localStorage . getItem ( 'timerActive' );
if ( timerPreference === 'true' ) {
timerSwitch . checked = true ;
}
Cache Management
Templates cache expires after 5 minutes (300,000ms) to balance freshness and performance.
Only changed templates trigger re-renders, not the entire list.
Search input is debounced to prevent excessive filtering operations.
Firebase Optimization
Offline mode toggle : db.goOffline() and db.goOnline() for controlled sync
Single read on load : Initial load uses .once() instead of continuous listeners
Selective listeners : Only active templates have change listeners
Security Considerations
Templates can contain HTML content. Ensure proper sanitization if displaying user-generated templates to prevent XSS attacks.
Access Control
Only authenticated users can create/edit templates
User attribution tracks who created each template
Firebase security rules enforce read/write permissions
Creating Templates Guide Step-by-step guide with examples
Caching Strategy Technical details on cache implementation
Firebase Integration How Firebase powers real-time features
Data Export Export templates and other data