feat(ui): add data caching and hash-based routing
- Implement localStorage-based caching in data-store to restore accounts, models, and usage data on load, improving initial render performance - Add hash-based routing in global store to sync active tab with URL, enabling browser back/forward navigation and direct linking to tabs
This commit is contained in:
@@ -33,13 +33,54 @@ document.addEventListener('alpine:init', () => {
|
|||||||
// For simplicity, let's keep relevant filters here.
|
// For simplicity, let's keep relevant filters here.
|
||||||
|
|
||||||
init() {
|
init() {
|
||||||
|
// Restore from cache first for instant render
|
||||||
|
this.loadFromCache();
|
||||||
|
|
||||||
// Watch filters to recompute
|
// Watch filters to recompute
|
||||||
// Alpine stores don't have $watch automatically unless inside a component?
|
// Alpine stores don't have $watch automatically unless inside a component?
|
||||||
// We can manually call compute when filters change.
|
// We can manually call compute when filters change.
|
||||||
},
|
},
|
||||||
|
|
||||||
|
loadFromCache() {
|
||||||
|
try {
|
||||||
|
const cached = localStorage.getItem('ag_data_cache');
|
||||||
|
if (cached) {
|
||||||
|
const data = JSON.parse(cached);
|
||||||
|
// Basic validty check
|
||||||
|
if (data.accounts && data.models) {
|
||||||
|
this.accounts = data.accounts;
|
||||||
|
this.models = data.models;
|
||||||
|
this.modelConfig = data.modelConfig || {};
|
||||||
|
this.usageHistory = data.usageHistory || {};
|
||||||
|
|
||||||
|
// Don't show loading on initial load if we have cache
|
||||||
|
this.initialLoad = false;
|
||||||
|
this.computeQuotaRows();
|
||||||
|
console.log('Restored data from cache');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.warn('Failed to load cache', e);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
saveToCache() {
|
||||||
|
try {
|
||||||
|
const cacheData = {
|
||||||
|
accounts: this.accounts,
|
||||||
|
models: this.models,
|
||||||
|
modelConfig: this.modelConfig,
|
||||||
|
usageHistory: this.usageHistory,
|
||||||
|
timestamp: Date.now()
|
||||||
|
};
|
||||||
|
localStorage.setItem('ag_data_cache', JSON.stringify(cacheData));
|
||||||
|
} catch (e) {
|
||||||
|
console.warn('Failed to save cache', e);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
async fetchData() {
|
async fetchData() {
|
||||||
// Only show skeleton on initial load, not on refresh
|
// Only show skeleton on initial load if we didn't restore from cache
|
||||||
if (this.initialLoad) {
|
if (this.initialLoad) {
|
||||||
this.loading = true;
|
this.loading = true;
|
||||||
}
|
}
|
||||||
@@ -67,6 +108,7 @@ document.addEventListener('alpine:init', () => {
|
|||||||
this.usageHistory = data.history;
|
this.usageHistory = data.history;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.saveToCache(); // Save fresh data
|
||||||
this.computeQuotaRows();
|
this.computeQuotaRows();
|
||||||
|
|
||||||
this.connectionStatus = 'connected';
|
this.connectionStatus = 'connected';
|
||||||
|
|||||||
@@ -5,6 +5,33 @@
|
|||||||
|
|
||||||
document.addEventListener('alpine:init', () => {
|
document.addEventListener('alpine:init', () => {
|
||||||
Alpine.store('global', {
|
Alpine.store('global', {
|
||||||
|
init() {
|
||||||
|
// Hash-based routing
|
||||||
|
const validTabs = ['dashboard', 'models', 'accounts', 'logs', 'settings'];
|
||||||
|
const getHash = () => window.location.hash.substring(1);
|
||||||
|
|
||||||
|
// 1. Initial load from hash
|
||||||
|
const initialHash = getHash();
|
||||||
|
if (validTabs.includes(initialHash)) {
|
||||||
|
this.activeTab = initialHash;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. Sync State -> URL
|
||||||
|
Alpine.effect(() => {
|
||||||
|
if (validTabs.includes(this.activeTab) && getHash() !== this.activeTab) {
|
||||||
|
window.location.hash = this.activeTab;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// 3. Sync URL -> State (Back/Forward buttons)
|
||||||
|
window.addEventListener('hashchange', () => {
|
||||||
|
const hash = getHash();
|
||||||
|
if (validTabs.includes(hash) && this.activeTab !== hash) {
|
||||||
|
this.activeTab = hash;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
// App State
|
// App State
|
||||||
version: '1.0.0',
|
version: '1.0.0',
|
||||||
activeTab: 'dashboard',
|
activeTab: 'dashboard',
|
||||||
|
|||||||
Reference in New Issue
Block a user