Upload index.html
Browse files- index.html +137 -37
index.html
CHANGED
|
@@ -1308,13 +1308,14 @@ Neutral market conditions</textarea>
|
|
| 1308 |
</div>
|
| 1309 |
|
| 1310 |
<script>
|
| 1311 |
-
// Configuration
|
| 1312 |
const config = {
|
| 1313 |
-
|
|
|
|
| 1314 |
wsUrl: (() => {
|
| 1315 |
const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:';
|
| 1316 |
const host = window.location.host;
|
| 1317 |
-
return `${protocol}//${host}/ws
|
| 1318 |
})(),
|
| 1319 |
autoRefreshInterval: 30000,
|
| 1320 |
maxRetries: 3
|
|
@@ -1341,50 +1342,108 @@ Neutral market conditions</textarea>
|
|
| 1341 |
console.log('📍 API Base URL:', config.apiBaseUrl);
|
| 1342 |
console.log('📡 WebSocket URL:', config.wsUrl);
|
| 1343 |
|
|
|
|
| 1344 |
initializeWebSocket();
|
| 1345 |
loadInitialData();
|
| 1346 |
startAutoRefresh();
|
| 1347 |
});
|
| 1348 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1349 |
// WebSocket Connection
|
| 1350 |
function initializeWebSocket() {
|
| 1351 |
updateWSStatus('connecting');
|
| 1352 |
|
| 1353 |
-
|
| 1354 |
-
|
| 1355 |
-
|
| 1356 |
-
|
| 1357 |
-
|
| 1358 |
-
|
| 1359 |
-
|
| 1360 |
-
|
| 1361 |
-
|
| 1362 |
-
|
| 1363 |
-
|
| 1364 |
-
|
| 1365 |
-
|
| 1366 |
-
|
| 1367 |
-
|
| 1368 |
-
|
| 1369 |
-
}
|
| 1370 |
-
}
|
| 1371 |
-
|
| 1372 |
-
|
| 1373 |
-
|
| 1374 |
-
|
| 1375 |
-
};
|
| 1376 |
-
|
| 1377 |
-
state.ws.onclose = () => {
|
| 1378 |
-
console.log('⚠️ WebSocket disconnected');
|
| 1379 |
-
state.wsConnected = false;
|
| 1380 |
-
updateWSStatus('disconnected');
|
| 1381 |
-
};
|
| 1382 |
-
} catch (error) {
|
| 1383 |
-
console.log('⚠️ WebSocket not available - using polling mode');
|
| 1384 |
updateWSStatus('disconnected');
|
| 1385 |
}
|
| 1386 |
}
|
| 1387 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1388 |
function updateWSStatus(status) {
|
| 1389 |
const statusEl = document.getElementById('wsStatus');
|
| 1390 |
const textEl = document.getElementById('wsStatusText');
|
|
@@ -1419,7 +1478,7 @@ Neutral market conditions</textarea>
|
|
| 1419 |
}
|
| 1420 |
}
|
| 1421 |
|
| 1422 |
-
// API Calls
|
| 1423 |
async function apiCall(endpoint, options = {}) {
|
| 1424 |
try {
|
| 1425 |
const url = `${config.apiBaseUrl}${endpoint}`;
|
|
@@ -1434,6 +1493,11 @@ Neutral market conditions</textarea>
|
|
| 1434 |
});
|
| 1435 |
|
| 1436 |
if (!response.ok) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1437 |
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
|
| 1438 |
}
|
| 1439 |
|
|
@@ -1447,6 +1511,42 @@ Neutral market conditions</textarea>
|
|
| 1447 |
}
|
| 1448 |
}
|
| 1449 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1450 |
async function loadInitialData() {
|
| 1451 |
showLoading();
|
| 1452 |
|
|
@@ -1475,7 +1575,7 @@ Neutral market conditions</textarea>
|
|
| 1475 |
async function loadHealth() {
|
| 1476 |
try {
|
| 1477 |
const data = await apiCall('/health');
|
| 1478 |
-
updateKPIs(data.components);
|
| 1479 |
|
| 1480 |
const statusBadge = document.getElementById('systemStatus');
|
| 1481 |
const statusText = document.getElementById('systemStatusText');
|
|
@@ -1522,7 +1622,7 @@ Neutral market conditions</textarea>
|
|
| 1522 |
document.getElementById('providersTableBody').innerHTML = `
|
| 1523 |
<tr>
|
| 1524 |
<td colspan="5" style="text-align: center; color: var(--text-muted); padding: 40px;">
|
| 1525 |
-
Failed to load providers
|
| 1526 |
</td>
|
| 1527 |
</tr>
|
| 1528 |
`;
|
|
|
|
| 1308 |
</div>
|
| 1309 |
|
| 1310 |
<script>
|
| 1311 |
+
// Configuration - آپدیت شده برای Hugging Face Spaces
|
| 1312 |
const config = {
|
| 1313 |
+
// استفاده از آدرس نسبی برای Hugging Face
|
| 1314 |
+
apiBaseUrl: '', // خالی بذارید تا از همون origin استفاده کنه
|
| 1315 |
wsUrl: (() => {
|
| 1316 |
const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:';
|
| 1317 |
const host = window.location.host;
|
| 1318 |
+
return `${protocol}//${host}/ws`;
|
| 1319 |
})(),
|
| 1320 |
autoRefreshInterval: 30000,
|
| 1321 |
maxRetries: 3
|
|
|
|
| 1342 |
console.log('📍 API Base URL:', config.apiBaseUrl);
|
| 1343 |
console.log('📡 WebSocket URL:', config.wsUrl);
|
| 1344 |
|
| 1345 |
+
discoverEndpoints(); // کشف endpoint های موجود
|
| 1346 |
initializeWebSocket();
|
| 1347 |
loadInitialData();
|
| 1348 |
startAutoRefresh();
|
| 1349 |
});
|
| 1350 |
|
| 1351 |
+
// تابع برای کشف endpoint های موجود
|
| 1352 |
+
async function discoverEndpoints() {
|
| 1353 |
+
console.log('🔍 Discovering available endpoints...');
|
| 1354 |
+
|
| 1355 |
+
const testEndpoints = [
|
| 1356 |
+
'/',
|
| 1357 |
+
'/health',
|
| 1358 |
+
'/api/health',
|
| 1359 |
+
'/info',
|
| 1360 |
+
'/api/info',
|
| 1361 |
+
'/providers',
|
| 1362 |
+
'/api/providers',
|
| 1363 |
+
'/status',
|
| 1364 |
+
'/api/status',
|
| 1365 |
+
'/api/crypto/market-overview',
|
| 1366 |
+
'/api/crypto/prices/top'
|
| 1367 |
+
];
|
| 1368 |
+
|
| 1369 |
+
const availableEndpoints = [];
|
| 1370 |
+
|
| 1371 |
+
for (const endpoint of testEndpoints) {
|
| 1372 |
+
try {
|
| 1373 |
+
const response = await fetch(endpoint);
|
| 1374 |
+
console.log(`${endpoint}: ${response.status}`);
|
| 1375 |
+
if (response.ok) {
|
| 1376 |
+
availableEndpoints.push(endpoint);
|
| 1377 |
+
console.log(`✅ Found: ${endpoint}`);
|
| 1378 |
+
}
|
| 1379 |
+
} catch (error) {
|
| 1380 |
+
console.log(`❌ Failed: ${endpoint}`);
|
| 1381 |
+
}
|
| 1382 |
+
}
|
| 1383 |
+
|
| 1384 |
+
console.log('📋 Available endpoints:', availableEndpoints);
|
| 1385 |
+
return availableEndpoints;
|
| 1386 |
+
}
|
| 1387 |
+
|
| 1388 |
// WebSocket Connection
|
| 1389 |
function initializeWebSocket() {
|
| 1390 |
updateWSStatus('connecting');
|
| 1391 |
|
| 1392 |
+
const wsEndpoints = [
|
| 1393 |
+
'/ws/live',
|
| 1394 |
+
'/ws',
|
| 1395 |
+
'/live',
|
| 1396 |
+
'/api/ws'
|
| 1397 |
+
];
|
| 1398 |
+
|
| 1399 |
+
for (const endpoint of wsEndpoints) {
|
| 1400 |
+
try {
|
| 1401 |
+
const wsUrl = `${window.location.protocol === 'https:' ? 'wss:' : 'ws:'}//${window.location.host}${endpoint}`;
|
| 1402 |
+
console.log(`🔄 Trying WebSocket: ${wsUrl}`);
|
| 1403 |
+
|
| 1404 |
+
state.ws = new WebSocket(wsUrl);
|
| 1405 |
+
setupWebSocketHandlers();
|
| 1406 |
+
break; // اگر موفق بود، بقیه رو امتحان نکن
|
| 1407 |
+
} catch (error) {
|
| 1408 |
+
console.log(`❌ WebSocket failed: ${endpoint}`);
|
| 1409 |
+
}
|
| 1410 |
+
}
|
| 1411 |
+
|
| 1412 |
+
if (!state.ws) {
|
| 1413 |
+
console.log('⚠️ No WebSocket endpoints available');
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1414 |
updateWSStatus('disconnected');
|
| 1415 |
}
|
| 1416 |
}
|
| 1417 |
|
| 1418 |
+
function setupWebSocketHandlers() {
|
| 1419 |
+
state.ws.onopen = () => {
|
| 1420 |
+
console.log('✅ WebSocket connected');
|
| 1421 |
+
state.wsConnected = true;
|
| 1422 |
+
updateWSStatus('connected');
|
| 1423 |
+
showToast('Connected', 'Real-time data stream active', 'success');
|
| 1424 |
+
};
|
| 1425 |
+
|
| 1426 |
+
state.ws.onmessage = (event) => {
|
| 1427 |
+
try {
|
| 1428 |
+
const data = JSON.parse(event.data);
|
| 1429 |
+
handleWSMessage(data);
|
| 1430 |
+
} catch (error) {
|
| 1431 |
+
console.error('Error parsing WebSocket message:', error);
|
| 1432 |
+
}
|
| 1433 |
+
};
|
| 1434 |
+
|
| 1435 |
+
state.ws.onerror = (error) => {
|
| 1436 |
+
console.error('❌ WebSocket error:', error);
|
| 1437 |
+
updateWSStatus('disconnected');
|
| 1438 |
+
};
|
| 1439 |
+
|
| 1440 |
+
state.ws.onclose = () => {
|
| 1441 |
+
console.log('⚠️ WebSocket disconnected');
|
| 1442 |
+
state.wsConnected = false;
|
| 1443 |
+
updateWSStatus('disconnected');
|
| 1444 |
+
};
|
| 1445 |
+
}
|
| 1446 |
+
|
| 1447 |
function updateWSStatus(status) {
|
| 1448 |
const statusEl = document.getElementById('wsStatus');
|
| 1449 |
const textEl = document.getElementById('wsStatusText');
|
|
|
|
| 1478 |
}
|
| 1479 |
}
|
| 1480 |
|
| 1481 |
+
// API Calls - آپدیت شده با endpoint های جایگزین
|
| 1482 |
async function apiCall(endpoint, options = {}) {
|
| 1483 |
try {
|
| 1484 |
const url = `${config.apiBaseUrl}${endpoint}`;
|
|
|
|
| 1493 |
});
|
| 1494 |
|
| 1495 |
if (!response.ok) {
|
| 1496 |
+
// اگر 404 باشه، endpoint های جایگزین رو چک کن
|
| 1497 |
+
if (response.status === 404) {
|
| 1498 |
+
console.log(`⚠️ Endpoint ${endpoint} not found, trying alternatives...`);
|
| 1499 |
+
return await tryAlternativeEndpoints(endpoint, options);
|
| 1500 |
+
}
|
| 1501 |
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
|
| 1502 |
}
|
| 1503 |
|
|
|
|
| 1511 |
}
|
| 1512 |
}
|
| 1513 |
|
| 1514 |
+
// تابع برای امتحان endpoint های جایگزین
|
| 1515 |
+
async function tryAlternativeEndpoints(originalEndpoint, options) {
|
| 1516 |
+
const alternatives = {
|
| 1517 |
+
'/api/providers': ['/providers', '/api/sources', '/status'],
|
| 1518 |
+
'/health': ['/api/health', '/status/health'],
|
| 1519 |
+
'/info': ['/api/info', '/system/info'],
|
| 1520 |
+
'/api/categories': ['/categories', '/api/groups'],
|
| 1521 |
+
'/api/rate-limits': ['/rate-limits', '/api/limits'],
|
| 1522 |
+
'/api/logs': ['/logs', '/api/events'],
|
| 1523 |
+
'/api/alerts': ['/alerts', '/api/notifications'],
|
| 1524 |
+
'/api/hf/health': ['/hf/health', '/api/huggingface/health'],
|
| 1525 |
+
'/api/hf/refresh': ['/hf/refresh', '/api/huggingface/refresh'],
|
| 1526 |
+
'/api/hf/registry': ['/hf/registry', '/api/huggingface/registry'],
|
| 1527 |
+
'/api/hf/search': ['/hf/search', '/api/huggingface/search'],
|
| 1528 |
+
'/api/hf/run-sentiment': ['/hf/sentiment', '/api/huggingface/sentiment']
|
| 1529 |
+
};
|
| 1530 |
+
|
| 1531 |
+
for (const altEndpoint of alternatives[originalEndpoint] || []) {
|
| 1532 |
+
try {
|
| 1533 |
+
const url = `${config.apiBaseUrl}${altEndpoint}`;
|
| 1534 |
+
console.log(`🔄 Trying alternative: ${altEndpoint}`);
|
| 1535 |
+
|
| 1536 |
+
const response = await fetch(url, options);
|
| 1537 |
+
if (response.ok) {
|
| 1538 |
+
const data = await response.json();
|
| 1539 |
+
console.log(`✅ Alternative endpoint worked: ${altEndpoint}`);
|
| 1540 |
+
return data;
|
| 1541 |
+
}
|
| 1542 |
+
} catch (error) {
|
| 1543 |
+
console.log(`❌ Alternative failed: ${altEndpoint}`);
|
| 1544 |
+
}
|
| 1545 |
+
}
|
| 1546 |
+
|
| 1547 |
+
throw new Error(`All endpoints failed for ${originalEndpoint}`);
|
| 1548 |
+
}
|
| 1549 |
+
|
| 1550 |
async function loadInitialData() {
|
| 1551 |
showLoading();
|
| 1552 |
|
|
|
|
| 1575 |
async function loadHealth() {
|
| 1576 |
try {
|
| 1577 |
const data = await apiCall('/health');
|
| 1578 |
+
updateKPIs(data.components || data);
|
| 1579 |
|
| 1580 |
const statusBadge = document.getElementById('systemStatus');
|
| 1581 |
const statusText = document.getElementById('systemStatusText');
|
|
|
|
| 1622 |
document.getElementById('providersTableBody').innerHTML = `
|
| 1623 |
<tr>
|
| 1624 |
<td colspan="5" style="text-align: center; color: var(--text-muted); padding: 40px;">
|
| 1625 |
+
Failed to load providers. Please check if the API endpoint is available.
|
| 1626 |
</td>
|
| 1627 |
</tr>
|
| 1628 |
`;
|