Ux Dashboard
Ecosistema completo para organización y gestión de contenido con interfaces espaciales
UX Dashboard Component
The UX Dashboard is a versatile layout component that provides a consistent, customizable UI framework for applications. It includes a header, sidebar navigation, and content area, with theme support and persistent configuration.
Core Features
- Responsive layout with adaptive sidebar and header
- Theme support with light, dark, and blue variants
- Persistent configurations saved to IndexedDB or localStorage
- Event-driven communication between dashboard instances
- Customizable sections for sidebar navigation
- Search functionality for filtering sections
- Project menu for application switching
Architecture
The UX Dashboard consists of several interconnected components and services:
Components
UxDashboardComponent- The main dashboard UI componentUxDashboardSections- A wrapper that uses the dashboard for the main app navigationUxDashboardDemoComponent- A demo component for testing and configuring dashboards
Services
UxDashboardStorageService- Handles saving and loading dashboard configurationsUxDashboardService- Provides dashboard registration and section management
Models
UxDashboardConfig- Configuration interface for the dashboardUxDashboardSection- Interface for sidebar navigation itemsUxDashboardTheme- Type for theme variants (light, dark, blue)
Configuration Persistence
The dashboard uses a robust persistence system to maintain configuration state across page refreshes:
IndexedDB Storage
- Primary storage mechanism for configurations
- Handles multiple dashboard instances with unique IDs
- Provides observable updates when configurations change
localStorage Fallback
- Used when IndexedDB is unavailable
- Provides a backup copy of configurations
Source Tracking
- Prevents circular update loops
- Each save operation includes a source ID
- Components can ignore updates from themselves
Implementing Theme Persistence
One of the key challenges in the dashboard system was ensuring theme persistence across page refreshes without causing update loops. Here's how we solved it:
The Challenge
When a dashboard component's theme changed, it would:
- Update its local configuration
- Save the configuration to IndexedDB
- Emit an update event
- Other components would detect this update and change their themes
- Those components would then save their configurations
- This would trigger more update events, creating an infinite loop
The Solution
We implemented a multi-layered approach to solve this issue:
Source Tracking
// When saving a configuration, identify the source this.dashboardStorageService.saveDashboardConfig( dashboardId, currentConfig, sections, 'component-identifier' ); // When receiving updates, ignore your own if (update.source === 'component-identifier') { console.log('Ignoring update from self'); return; }Hash-Based Change Detection
// Create a hash of the current configuration const configString = JSON.stringify({ config: currentConfig, sections: sections }); const currentHash = this.hashString(configString); // Skip saving if unchanged if (currentHash === this.lastSavedConfigHash) { console.log('No changes detected, skipping save'); return; }Priority Theme Updates
// Special handling for theme updates if (update.source === 'theme-change-immediate') { // Apply theme immediately without triggering further saves this.updateTheme(theme, false); // false means don't save return; // Skip further processing }Selective Update Application
// Update the theme with an option to skip saving private updateTheme(theme: UxDashboardTheme, shouldSave: boolean = true): void { // Update the dashboard configuration this.dashboardConfig.update(config => ({ ...config, theme: theme })); // Apply theme to body this.applyThemeToBody(theme); // Save only if requested if (shouldSave) { this.saveConfiguration(); } }
Usage Example
Here's how theme changes are handled in the UxDashboardDemoComponent:
onThemeSelected(event: { groupId: string; value: string }): void {
if (event.groupId === 'theme') {
// Update configuration with new theme
const updatedConfig = { ...this.dashboardConfig() };
updatedConfig.theme = event.value as UxDashboardTheme;
this.dashboardConfig.set(updatedConfig);
// Special handling for main dashboard
if (this.customDashboardId() === 'main-ux-dashboard') {
// Use a special source identifier for theme changes
this.dashboardStorageService.saveDashboardConfig(
'main-ux-dashboard',
updatedConfig,
this.dashboardSections(),
'theme-change-immediate'
).subscribe();
} else {
// Normal save for other dashboards
this.saveConfiguration();
}
}
}
Lessons Learned
Through our implementation of the UX Dashboard system, we learned several important lessons:
Event-based updates are better than polling
- Initially, we used interval-based polling to check for configuration changes
- Switching to an event-based system using RxJS subjects improved performance and reliability
Identify update sources to prevent loops
- Including a source identifier with each update allows components to ignore their own updates
- This prevents circular update chains that can cause infinite loops
Create clear ownership boundaries
- The main dashboard (
main-ux-dashboard) needed special handling - Establishing clear ownership and priority rules for updates resolved conflicts
- The main dashboard (
Implement hash-based change detection
- Avoid unnecessary saves by checking if configurations have actually changed
- Simple hash functions can dramatically reduce database operations
Troubleshooting
Theme Not Persisting After Refresh
If themes aren't persisting across page refreshes:
- Check that the
persistUIStateproperty is set totruein the dashboard configuration - Verify that the
UxDashboardStorageServiceis properly initialized - Look for error messages related to IndexedDB access in the console
- Ensure that the dashboard ID is consistent across refreshes
Circular Update Loops
If you're experiencing infinite update loops:
- Check that components are properly tracking the source of updates
- Ensure components ignore updates that originated from themselves
- Verify that hash-based change detection is working correctly
- Add console logs to track the flow of updates through the system
Best Practices
Always specify a unique dashboard ID
<app-ux-dashboard [id]="'my-unique-dashboard-id'"></app-ux-dashboard>Use signals for reactive state management
dashboardConfig = signal<UxDashboardConfig>({...});Include source identifiers when saving
storageService.saveDashboardConfig(id, config, sections, 'my-component-id');Implement selective update handling
if (update.source !== myComponentId && needsProcessing(update)) { // Process the update }