trade-flow-predictor / static /js /data_manager.js
jomasego's picture
Upload static/js/data_manager.js with huggingface_hub
c21a1ba verified
/**
* Data Manager Module
* Handles caching and retrieval of trade data to reduce API calls
*/
const DataManager = (function() {
// In-memory cache
const memoryCache = {};
// Check if localStorage is available
const storageAvailable = function() {
try {
const storage = window.localStorage;
const x = '__storage_test__';
storage.setItem(x, x);
storage.removeItem(x);
return true;
} catch(e) {
return false;
}
};
// Generate a cache key from request parameters
const generateCacheKey = function(params) {
return `trade_data_${params.reporterCode}_${params.partnerCode}_${params.period}_${params.cmdCode}_${params.flowCode || 'all'}`;
};
// Save data to localStorage and memory cache
const saveToCache = function(params, data) {
const key = generateCacheKey(params);
// Save to memory cache
memoryCache[key] = {
timestamp: Date.now(),
data: data
};
// Save to localStorage if available
if (storageAvailable()) {
try {
localStorage.setItem(key, JSON.stringify({
timestamp: Date.now(),
data: data
}));
} catch(e) {
console.warn('Failed to save to localStorage:', e);
}
}
};
// Get data from cache
const getFromCache = function(params) {
const key = generateCacheKey(params);
// Try memory cache first
if (memoryCache[key]) {
return memoryCache[key].data;
}
// Try localStorage
if (storageAvailable()) {
try {
const storedData = localStorage.getItem(key);
if (storedData) {
const parsed = JSON.parse(storedData);
// Refresh memory cache with this data
memoryCache[key] = parsed;
return parsed.data;
}
} catch(e) {
console.warn('Failed to retrieve from localStorage:', e);
}
}
return null;
};
// Check if data is cached
const isDataCached = function(params) {
return getFromCache(params) !== null;
};
// Export CSV from data
const exportToCsv = function(data, filename = 'trade_data.csv') {
if (!data || !data.columns || !data.rows || data.rows.length === 0) {
console.error('Invalid data for CSV export');
return false;
}
// Create CSV header row
let csv = data.columns.join(',') + '\n';
// Add data rows
data.rows.forEach(row => {
const rowValues = data.columns.map(col => {
// Handle value that might contain commas
const value = row[col] !== undefined ? row[col] : '';
if (typeof value === 'string' && (value.includes(',') || value.includes('"') || value.includes('\n'))) {
return `"${value.replace(/"/g, '""')}"`;
}
return value;
});
csv += rowValues.join(',') + '\n';
});
// Create and trigger download
const blob = new Blob([csv], { type: 'text/csv;charset=utf-8;' });
const url = URL.createObjectURL(blob);
const link = document.createElement('a');
link.setAttribute('href', url);
link.setAttribute('download', filename);
link.style.visibility = 'hidden';
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
return true;
};
// List all cached data sets
const listCachedData = function() {
const cachedData = [];
// List from memory cache
for (const key in memoryCache) {
if (key.startsWith('trade_data_')) {
const parts = key.split('_');
cachedData.push({
key: key,
reporter: parts[2],
partner: parts[3],
year: parts[4],
commodity: parts[5],
flow: parts[6],
timestamp: new Date(memoryCache[key].timestamp).toLocaleString()
});
}
}
// Combine with any localStorage data not in memory
if (storageAvailable()) {
for (let i = 0; i < localStorage.length; i++) {
const key = localStorage.key(i);
if (key.startsWith('trade_data_') && !memoryCache[key]) {
try {
const data = JSON.parse(localStorage.getItem(key));
const parts = key.split('_');
cachedData.push({
key: key,
reporter: parts[2],
partner: parts[3],
year: parts[4],
commodity: parts[5],
flow: parts[6],
timestamp: new Date(data.timestamp).toLocaleString()
});
} catch(e) {
console.warn('Failed to parse localStorage item:', key);
}
}
}
}
return cachedData;
};
// Clear specific cache entry
const clearCacheEntry = function(key) {
// Clear from memory
if (memoryCache[key]) {
delete memoryCache[key];
}
// Clear from localStorage
if (storageAvailable()) {
localStorage.removeItem(key);
}
};
// Clear all cache
const clearAllCache = function() {
// Clear memory cache
for (const key in memoryCache) {
if (key.startsWith('trade_data_')) {
delete memoryCache[key];
}
}
// Clear localStorage
if (storageAvailable()) {
const keysToRemove = [];
for (let i = 0; i < localStorage.length; i++) {
const key = localStorage.key(i);
if (key.startsWith('trade_data_')) {
keysToRemove.push(key);
}
}
// Remove items separately to avoid index issues
keysToRemove.forEach(key => localStorage.removeItem(key));
}
};
// Public API
return {
saveToCache,
getFromCache,
isDataCached,
exportToCsv,
listCachedData,
clearCacheEntry,
clearAllCache
};
})();