Really-amin commited on
Commit
bfb736b
·
verified ·
1 Parent(s): d09c139

Upload 2 files

Browse files
Files changed (1) hide show
  1. index.html +644 -100
index.html CHANGED
@@ -1615,7 +1615,252 @@
1615
  tbody tr:last-child td:last-child {
1616
  border-bottom-right-radius: 12px;
1617
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1618
  </style>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1619
  </head>
1620
 
1621
  <body>
@@ -1667,7 +1912,10 @@
1667
  </div>
1668
  </div>
1669
  <div class="header-actions">
1670
- <div class="live-indicator">● LIVE</div>
 
 
 
1671
  <div class="status-badge">
1672
  <div class="status-dot"></div>
1673
  <span id="statusText">All Systems Operational</span>
@@ -1677,15 +1925,42 @@
1677
 
1678
  <!-- Tabs -->
1679
  <div class="tabs">
1680
- <button class="tab active" onclick="switchTab('market')">📊 Market</button>
1681
- <button class="tab" onclick="switchTab('monitor')">📡 API Monitor</button>
1682
- <button class="tab" onclick="switchTab('advanced')">⚡ Advanced</button>
1683
- <button class="tab" onclick="switchTab('admin')">⚙️ Admin</button>
1684
- <button class="tab" onclick="switchTab('hf')">🤗 HuggingFace</button>
1685
- <button class="tab" onclick="switchTab('pools')">🔄 Pools</button>
1686
- <button class="tab" onclick="switchTab('logs')">📋 Logs</button>
1687
- <button class="tab" onclick="switchTab('resources')">📦 Resources</button>
1688
- <button class="tab" onclick="switchTab('reports')">📊 Reports</button>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1689
  </div>
1690
  </div>
1691
 
@@ -1789,13 +2064,19 @@
1789
  <!-- Market Table -->
1790
  <div class="market-section">
1791
  <div class="section-header">
1792
- <div class="section-title gradient-text">💎 Live Market Data</div>
1793
- <button class="refresh-btn ripple" onclick="loadMarketData()" data-tooltip="به‌روزرسانی داده‌های بازار">↻ Refresh</button>
 
 
 
 
 
 
1794
  </div>
1795
 
1796
  <!-- Search Bar -->
1797
  <div class="search-container">
1798
- <span class="search-icon">🔍</span>
1799
  <input type="text" class="search-input" id="marketSearch" placeholder="جستجوی ارز دیجیتال (مثال: Bitcoin, BTC, Ethereum)..." oninput="filterMarketTable()">
1800
  </div>
1801
 
@@ -1803,9 +2084,18 @@
1803
  <div class="filter-chips">
1804
  <button class="filter-chip active" onclick="filterByCategory('all')">همه</button>
1805
  <button class="filter-chip" onclick="filterByCategory('top10')">Top 10</button>
1806
- <button class="filter-chip" onclick="filterByCategory('gainers')">📈 در حال رشد</button>
1807
- <button class="filter-chip" onclick="filterByCategory('losers')">📉 در حال سقوط</button>
1808
- <button class="filter-chip" onclick="filterByCategory('volume')">💹 حجم بالا</button>
 
 
 
 
 
 
 
 
 
1809
  </div>
1810
  <div style="overflow-x: auto;">
1811
  <table id="marketTable">
@@ -1854,7 +2144,10 @@
1854
 
1855
  <!-- Trending Section -->
1856
  <div class="market-section">
1857
- <div class="section-title" style="margin-bottom: 20px;">🔥 Trending Now</div>
 
 
 
1858
  <div id="trendingGrid"
1859
  style="display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 15px;">
1860
  <div class="loading">
@@ -1933,8 +2226,14 @@
1933
 
1934
  <div class="market-section">
1935
  <div class="section-header">
1936
- <div class="section-title">📊 API Providers Status</div>
1937
- <button class="refresh-btn ripple" onclick="loadMonitorData()">↻ Refresh</button>
 
 
 
 
 
 
1938
  </div>
1939
  <div style="overflow-x: auto;">
1940
  <table>
@@ -1957,7 +2256,10 @@
1957
  </div>
1958
 
1959
  <div class="market-section">
1960
- <div class="section-title" style="margin-bottom: 20px;">🤗 HuggingFace Sentiment Analysis</div>
 
 
 
1961
  <div class="form-group">
1962
  <label class="form-label">Enter crypto-related text (one per line):</label>
1963
  <textarea class="form-textarea" id="sentimentText" rows="5"
@@ -1965,7 +2267,10 @@
1965
  ETH looks weak
1966
  Market is bullish today</textarea>
1967
  </div>
1968
- <button class="refresh-btn ripple" onclick="runSentiment()">🧠 Analyze Sentiment</button>
 
 
 
1969
  <div id="sentimentResult"
1970
  style="margin-top: 20px; padding: 20px; background: rgba(17, 24, 39, 0.6); border-radius: 12px; text-align: center; font-size: 36px; font-weight: 900;">
1971
  —</div>
@@ -2099,12 +2404,18 @@ Market is bullish today</textarea>
2099
  </div>
2100
 
2101
  <div class="market-section">
2102
- <div class="section-title" style="margin-bottom: 20px;">📋 Current API Sources</div>
 
 
 
2103
  <div id="apisList">Loading...</div>
2104
  </div>
2105
 
2106
  <div class="market-section">
2107
- <div class="section-title" style="margin-bottom: 20px;">⚙️ Settings</div>
 
 
 
2108
  <div class="form-group">
2109
  <label class="form-label">API Check Interval (seconds)</label>
2110
  <input type="number" class="form-input" id="checkInterval" value="30" min="10" max="300">
@@ -2117,7 +2428,10 @@ Market is bullish today</textarea>
2117
  </div>
2118
 
2119
  <div class="market-section">
2120
- <div class="section-title" style="margin-bottom: 20px;">📊 Statistics</div>
 
 
 
2121
  <div class="stats-grid">
2122
  <div class="stat-card">
2123
  <div class="stat-value" id="statTotal">0</div>
@@ -2139,8 +2453,14 @@ Market is bullish today</textarea>
2139
  <div id="tab-hf" class="tab-content">
2140
  <div class="market-section">
2141
  <div class="section-header">
2142
- <div class="section-title">📊 Health Status</div>
2143
- <button class="refresh-btn" onclick="loadHFHealth()">🔄 Refresh</button>
 
 
 
 
 
 
2144
  </div>
2145
  <pre id="healthOutput"
2146
  style="background: #1e293b; color: #e2e8f0; padding: 15px; border-radius: 8px; overflow-x: auto; font-size: 12px; max-height: 200px; overflow-y: auto;">Loading...</pre>
@@ -2185,7 +2505,10 @@ Market is bullish today</textarea>
2185
  </div>
2186
 
2187
  <div class="market-section">
2188
- <div class="section-title" style="margin-bottom: 20px;">💭 Sentiment Analysis</div>
 
 
 
2189
  <div class="form-group">
2190
  <label class="form-label">Enter text samples (one per line):</label>
2191
  <textarea class="form-textarea" id="sentimentTexts" rows="5"
@@ -2193,7 +2516,10 @@ Market is bullish today</textarea>
2193
  ETH looks weak
2194
  Crypto market is bullish today</textarea>
2195
  </div>
2196
- <button class="refresh-btn" onclick="doSentiment()">🧠 Run Sentiment Analysis</button>
 
 
 
2197
  <div id="voteDisplay"
2198
  style="margin-top: 20px; padding: 20px; background: rgba(17, 24, 39, 0.6); border-radius: 12px; text-align: center; font-size: 36px; font-weight: 900;">
2199
  —</div>
@@ -2206,17 +2532,30 @@ Crypto market is bullish today</textarea>
2206
  <div id="tab-logs" class="tab-content">
2207
  <div class="market-section">
2208
  <div class="section-header">
2209
- <div class="section-title">📋 Log Management</div>
 
 
 
2210
  <div style="display: flex; gap: 10px;">
2211
- <button class="refresh-btn" onclick="loadLogs()">🔄 Refresh</button>
2212
- <button class="refresh-btn" onclick="exportLogsJSON()"
2213
- style="background: rgba(16, 185, 129, 0.2); color: var(--accent-green);">💾 Export
2214
- JSON</button>
2215
- <button class="refresh-btn" onclick="exportLogsCSV()"
2216
- style="background: rgba(16, 185, 129, 0.2); color: var(--accent-green);">📊 Export
2217
- CSV</button>
2218
- <button class="refresh-btn" onclick="clearAllLogs()"
2219
- style="background: rgba(239, 68, 68, 0.2); color: var(--accent-red);">🗑️ Clear</button>
 
 
 
 
 
 
 
 
 
 
2220
  </div>
2221
  </div>
2222
 
@@ -2399,16 +2738,42 @@ Crypto market is bullish today</textarea>
2399
 
2400
  <!-- Reports Tab -->
2401
  <div id="tab-reports" class="tab-content">
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2402
  <div class="market-section">
2403
  <div class="section-header">
2404
- <div class="section-title">🔍 اشکال‌یابی خودکار</div>
 
 
 
2405
  <div style="display: flex; gap: 10px;">
2406
- <button class="refresh-btn" onclick="runDiagnostics(false)"
2407
- style="background: rgba(59, 130, 246, 0.2); color: var(--accent-blue);">🔍 بررسی</button>
2408
- <button class="refresh-btn" onclick="runDiagnostics(true)"
2409
- style="background: rgba(16, 185, 129, 0.2); color: var(--accent-green);">🔧 بررسی و
2410
- تعمیر</button>
2411
- <button class="refresh-btn" onclick="loadReports()">🔄 به‌روزرسانی</button>
 
 
 
 
 
 
 
 
2412
  </div>
2413
  </div>
2414
 
@@ -2422,8 +2787,14 @@ Crypto market is bullish today</textarea>
2422
 
2423
  <div class="market-section">
2424
  <div class="section-header">
2425
- <div class="section-title">🤖 گزارش Auto-Discovery Service</div>
2426
- <button class="refresh-btn" onclick="loadDiscoveryReport()">🔄 به‌روزرسانی</button>
 
 
 
 
 
 
2427
  </div>
2428
  <div id="discoveryReport">
2429
  <div class="loading">
@@ -2434,8 +2805,14 @@ Crypto market is bullish today</textarea>
2434
 
2435
  <div class="market-section">
2436
  <div class="section-header">
2437
- <div class="section-title">🧠 گزارش وضعیت مدل‌های HuggingFace</div>
2438
- <button class="refresh-btn" onclick="loadModelsReport()">🔄 به‌روزرسانی</button>
 
 
 
 
 
 
2439
  </div>
2440
  <div id="modelsReport">
2441
  <div class="loading">
@@ -2668,7 +3045,7 @@ Crypto market is bullish today</textarea>
2668
 
2669
  // Call updateStats with validated data - double check before calling
2670
  if (stats && stats.market && typeof stats.market === 'object' && !Array.isArray(stats.market)) {
2671
- updateStats(stats, sentiment);
2672
  } else {
2673
  console.error('Failed final validation before updateStats:', { stats, sentiment });
2674
  throw new Error('داده‌های stats.market نامعتبر است');
@@ -2761,15 +3138,15 @@ Crypto market is bullish today</textarea>
2761
  if (sentimentLabelEl) {
2762
  sentimentLabelEl.innerHTML = `<span>${classification}</span>`;
2763
 
2764
- if (fg < 25) {
2765
  sentimentLabelEl.style.color = 'var(--accent-red)';
2766
- } else if (fg < 45) {
2767
  sentimentLabelEl.style.color = 'var(--accent-yellow)';
2768
- } else if (fg < 55) {
2769
  sentimentLabelEl.style.color = 'var(--text-secondary)';
2770
- } else if (fg < 75) {
2771
  sentimentLabelEl.style.color = 'var(--accent-blue)';
2772
- } else {
2773
  sentimentLabelEl.style.color = 'var(--accent-green)';
2774
  }
2775
  }
@@ -2783,7 +3160,7 @@ Crypto market is bullish today</textarea>
2783
  function updateMarketTable(cryptos) {
2784
  try {
2785
  if (!cryptos || !Array.isArray(cryptos) || cryptos.length === 0) {
2786
- const tbody = document.getElementById('marketTableBody');
2787
  if (tbody) {
2788
  tbody.innerHTML = '<tr><td colspan="6" style="text-align: center; padding: 40px; color: var(--text-secondary);">هیچ داده‌ای یافت نشد</td></tr>';
2789
  }
@@ -2808,22 +3185,22 @@ Crypto market is bullish today</textarea>
2808
 
2809
  return `
2810
  <tr data-name="${name.toLowerCase()}" data-symbol="${symbol.toLowerCase()}" data-change="${change24h}" data-rank="${crypto.rank || index + 1}">
2811
- <td style="font-weight: 700; color: var(--text-secondary);">${crypto.rank || index + 1}</td>
2812
- <td>
2813
- <div class="crypto-name">
2814
  ${crypto.image ? `<img src="${crypto.image}" class="crypto-img" alt="${symbol}" onerror="this.style.display='none'">` :
2815
  `<div class="crypto-img" style="background: linear-gradient(135deg, #3b82f6, #8b5cf6); display: flex; align-items: center; justify-content: center; font-weight: 700; color: white;">${symbol[0] || '?'}</div>`}
2816
- <div>
2817
  <div style="font-weight: 600;">${name}</div>
2818
  <div class="crypto-symbol">${symbol}</div>
2819
- </div>
2820
- </div>
2821
- </td>
2822
  <td class="price number-counter">$${price.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 6 })}</td>
2823
  <td><span class="change ${changeClass} pulse-data">${changeIcon} ${change24h >= 0 ? '+' : ''}${change24h.toFixed(2)}%</span></td>
2824
  <td style="font-weight: 600;">$${(marketCap / 1e9).toFixed(2)}B</td>
2825
  <td style="color: var(--text-secondary);">$${(volume24h / 1e9).toFixed(2)}B</td>
2826
- </tr>
2827
  `;
2828
  }).join('');
2829
  } catch (error) {
@@ -2837,7 +3214,7 @@ Crypto market is bullish today</textarea>
2837
 
2838
  function updateTrending(trending) {
2839
  try {
2840
- const grid = document.getElementById('trendingGrid');
2841
  if (!grid) return;
2842
 
2843
  if (!trending || !Array.isArray(trending) || trending.length === 0) {
@@ -2849,14 +3226,14 @@ Crypto market is bullish today</textarea>
2849
  const name = coin.name || 'نامشخص';
2850
  const symbol = coin.symbol || 'N/A';
2851
  return `
2852
- <div style="background: rgba(59, 130, 246, 0.1); border: 1px solid rgba(59, 130, 246, 0.2); border-radius: 12px; padding: 15px; display: flex; align-items: center; gap: 12px;">
2853
- <div style="font-size: 20px; font-weight: 900; color: var(--accent-yellow);">#${index + 1}</div>
2854
  ${coin.thumb ? `<img src="${coin.thumb}" style="width: 32px; height: 32px; border-radius: 8px;" onerror="this.style.display='none'">` : ''}
2855
- <div>
2856
  <div style="font-weight: 600;">${name}</div>
2857
  <div style="font-size: 12px; color: var(--text-secondary);">${symbol}</div>
2858
- </div>
2859
- </div>
2860
  `;
2861
  }).join('');
2862
  } catch (error) {
@@ -2870,18 +3247,18 @@ Crypto market is bullish today</textarea>
2870
 
2871
  function updateDeFi(defi) {
2872
  try {
2873
- const list = document.getElementById('defiList');
2874
  if (!list) return;
2875
 
2876
  const protocols = defi && defi.protocols ? defi.protocols : [];
2877
  const totalTvl = defi && defi.total_tvl ? defi.total_tvl : 0;
2878
 
2879
- list.innerHTML = `
2880
  <div class="stat-card" style="margin-bottom: 20px; text-align: center; background: linear-gradient(135deg, rgba(59, 130, 246, 0.2), rgba(139, 92, 246, 0.2));">
2881
  <div class="stat-value gradient-text" style="font-size: 42px; margin-bottom: 8px;">$${(totalTvl / 1e9).toFixed(2)}B</div>
2882
  <div class="stat-label" style="font-size: 16px;">Total Value Locked</div>
2883
- </div>
2884
- <div style="display: grid; gap: 12px;">
2885
  ${protocols.length > 0 ? protocols.map((p, i) => {
2886
  const name = p.name || 'نامشخص';
2887
  const chain = p.chain || 'N/A';
@@ -2891,21 +3268,21 @@ Crypto market is bullish today</textarea>
2891
  return `
2892
  <div class="stat-card" style="animation-delay: ${i * 0.05}s; cursor: pointer;" onclick="showToast('${name}: $${(tvl / 1e9).toFixed(2)}B TVL', 'info', 'DeFi Protocol')">
2893
  <div style="display: flex; justify-content: space-between; align-items: center;">
2894
- <div>
2895
  <div style="font-weight: 700; font-size: 16px; margin-bottom: 4px;">${i + 1}. ${name}</div>
2896
  <div style="font-size: 12px; color: var(--text-secondary); display: flex; align-items: center; gap: 6px;">
2897
  <span>🔗</span> <span>${chain}</span>
2898
  </div>
2899
- </div>
2900
- <div style="text-align: right;">
2901
  <div class="stat-value" style="font-size: 18px; margin-bottom: 4px;">$${(tvl / 1e9).toFixed(2)}B</div>
2902
  <div class="stat-change ${changeClass}" style="font-size: 13px;">
2903
  ${change24h >= 0 ? '📈' : '📉'} ${change24h >= 0 ? '+' : ''}${change24h.toFixed(2)}%
2904
- </div>
2905
- </div>
2906
- </div>
2907
  </div>
2908
- `;
 
 
 
2909
  }).join('') : '<div class="empty-state"><div class="empty-state-icon">📦</div><div>هیچ پروتکلی یافت نشد</div></div>'}
2910
  </div>
2911
  `;
@@ -3002,7 +3379,7 @@ Crypto market is bullish today</textarea>
3002
  window.wsClient.on('stats_update', (message) => {
3003
  console.log('📊 Stats update:', message.data);
3004
  if (typeof updateOnlineStats === 'function') {
3005
- updateOnlineStats(message.data);
3006
  }
3007
  });
3008
 
@@ -3030,10 +3407,10 @@ Crypto market is bullish today</textarea>
3030
  // درخواست آمار هر 10 ثانیه (فقط یک بار تنظیم شود)
3031
  if (!wsStatsInterval) {
3032
  wsStatsInterval = setInterval(() => {
3033
- if (window.wsClient && window.wsClient.isConnected) {
3034
- window.wsClient.requestStats();
3035
- }
3036
- }, 10000);
3037
  }
3038
  } else {
3039
  wsConnectAttempts++;
@@ -3042,7 +3419,7 @@ Crypto market is bullish today</textarea>
3042
  if (wsConnectAttempts % 5 === 0 || wsConnectAttempts === 1) {
3043
  console.log(`⏳ در انتظار WebSocket Client... (${wsConnectAttempts}/${MAX_WS_CONNECT_ATTEMPTS})`);
3044
  }
3045
- setTimeout(connectWebSocket, 1000);
3046
  } else {
3047
  console.warn('⚠️ WebSocket Client پس از ' + MAX_WS_CONNECT_ATTEMPTS + ' تلاش آماده نشد. ممکن است فایل websocket-client.js لود نشده باشد یا WebSocket پشتیبانی نشود.');
3048
  console.warn('⚠️ بررسی کنید که فایل /static/js/websocket-client.js به درستی لود شده باشد.');
@@ -3136,21 +3513,21 @@ Crypto market is bullish today</textarea>
3136
  if (providers.length === 0) {
3137
  tbody.innerHTML = '<tr><td colspan="5" style="text-align: center; padding: 40px; color: var(--text-secondary);">هیچ APIای یافت نشد</td></tr>';
3138
  } else {
3139
- tbody.innerHTML = providers.map(p => {
3140
- let statusClass = 'badge-success';
3141
- if (p.status === 'offline') statusClass = 'badge-danger';
3142
- else if (p.status === 'degraded') statusClass = 'badge-warning';
3143
 
3144
- return `
3145
- <tr>
3146
  <td><strong>${p.name || 'نامشخص'}</strong></td>
3147
  <td><span class="badge badge-info">${p.category || 'نامشخص'}</span></td>
3148
  <td><span class="badge ${statusClass}">${(p.status || 'unknown').toUpperCase()}</span></td>
3149
  <td>${p.response_time_ms || p.avg_response_time_ms || 0}ms</td>
3150
  <td style="color: var(--text-secondary); font-size: 13px;">${p.last_fetch ? new Date(p.last_fetch).toLocaleTimeString() : 'نامشخص'}</td>
3151
- </tr>
3152
- `;
3153
- }).join('');
3154
  }
3155
  }
3156
  } catch (error) {
@@ -3847,7 +4224,7 @@ Crypto market is bullish today</textarea>
3847
  // Auto hide after 3 seconds
3848
  setTimeout(() => {
3849
  hideFeedback();
3850
- }, 3000);
3851
  }
3852
  }
3853
 
@@ -4278,6 +4655,158 @@ Crypto market is bullish today</textarea>
4278
  ]);
4279
  }
4280
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4281
  async function runDiagnostics(autoFix = false) {
4282
  const resultsDiv = document.getElementById('diagnosticsResults');
4283
  resultsDiv.innerHTML = '<div class="loading"><div class="spinner"></div></div>';
@@ -4289,10 +4818,19 @@ Crypto market is bullish today</textarea>
4289
  const report = await response.json();
4290
 
4291
  displayDiagnosticsReport(report);
4292
- showToast(`✅ اشکال‌یابی انجام شد (${report.total_issues} مشکل یافت شد)`, 'success');
 
 
 
 
 
 
4293
  } catch (error) {
4294
- resultsDiv.innerHTML = `<div class="alert alert-error">❌ خطا: ${error.message}</div>`;
4295
- showToast('❌ خطا در اجرای اشکال‌یابی', 'error');
 
 
 
4296
  }
4297
  }
4298
 
@@ -4406,6 +4944,12 @@ Crypto market is bullish today</textarea>
4406
  }
4407
 
4408
  displayDiagnosticsReport(report);
 
 
 
 
 
 
4409
  } catch (error) {
4410
  console.error('Error loading last diagnostics:', error);
4411
  }
 
1615
  tbody tr:last-child td:last-child {
1616
  border-bottom-right-radius: 12px;
1617
  }
1618
+
1619
+ /* SVG Icon Styles */
1620
+ .icon {
1621
+ width: 20px;
1622
+ height: 20px;
1623
+ display: inline-flex;
1624
+ align-items: center;
1625
+ justify-content: center;
1626
+ flex-shrink: 0;
1627
+ }
1628
+
1629
+ .icon-sm {
1630
+ width: 16px;
1631
+ height: 16px;
1632
+ }
1633
+
1634
+ .icon-md {
1635
+ width: 24px;
1636
+ height: 24px;
1637
+ }
1638
+
1639
+ .icon-lg {
1640
+ width: 32px;
1641
+ height: 32px;
1642
+ }
1643
+
1644
+ .icon-xl {
1645
+ width: 48px;
1646
+ height: 48px;
1647
+ }
1648
+
1649
+ .icon svg {
1650
+ width: 100%;
1651
+ height: 100%;
1652
+ stroke: currentColor;
1653
+ fill: none;
1654
+ stroke-width: 2;
1655
+ stroke-linecap: round;
1656
+ stroke-linejoin: round;
1657
+ }
1658
+
1659
+ .icon-filled svg {
1660
+ fill: currentColor;
1661
+ stroke: none;
1662
+ }
1663
+
1664
+ .icon-gradient {
1665
+ background: linear-gradient(135deg, var(--accent-blue), var(--accent-purple));
1666
+ -webkit-background-clip: text;
1667
+ -webkit-text-fill-color: transparent;
1668
+ background-clip: text;
1669
+ }
1670
+
1671
+ /* Tab Icons */
1672
+ .tab-icon {
1673
+ width: 18px;
1674
+ height: 18px;
1675
+ margin-right: 8px;
1676
+ display: inline-flex;
1677
+ align-items: center;
1678
+ justify-content: center;
1679
+ }
1680
+
1681
+ .tab-icon svg {
1682
+ width: 100%;
1683
+ height: 100%;
1684
+ }
1685
+
1686
+ /* Status Icons */
1687
+ .status-icon {
1688
+ width: 20px;
1689
+ height: 20px;
1690
+ display: inline-flex;
1691
+ align-items: center;
1692
+ justify-content: center;
1693
+ }
1694
+
1695
+ .status-icon-success svg {
1696
+ color: var(--accent-green);
1697
+ }
1698
+
1699
+ .status-icon-error svg {
1700
+ color: var(--accent-red);
1701
+ }
1702
+
1703
+ .status-icon-warning svg {
1704
+ color: var(--accent-yellow);
1705
+ }
1706
+
1707
+ .status-icon-info svg {
1708
+ color: var(--accent-blue);
1709
+ }
1710
  </style>
1711
+
1712
+ <!-- SVG Icon Definitions -->
1713
+ <svg style="display: none;" xmlns="http://www.w3.org/2000/svg">
1714
+ <!-- Success Icon -->
1715
+ <symbol id="icon-success" viewBox="0 0 24 24">
1716
+ <circle cx="12" cy="12" r="10" fill="none" stroke="currentColor" stroke-width="2"/>
1717
+ <path d="M8 12l2 2 4-4" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
1718
+ </symbol>
1719
+
1720
+ <!-- Error Icon -->
1721
+ <symbol id="icon-error" viewBox="0 0 24 24">
1722
+ <circle cx="12" cy="12" r="10" fill="none" stroke="currentColor" stroke-width="2"/>
1723
+ <path d="M12 8v4M12 16h.01" stroke="currentColor" stroke-width="2" stroke-linecap="round"/>
1724
+ </symbol>
1725
+
1726
+ <!-- Warning Icon -->
1727
+ <symbol id="icon-warning" viewBox="0 0 24 24">
1728
+ <path d="M12 2L2 22h20L12 2z" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
1729
+ <path d="M12 9v4M12 17h.01" stroke="currentColor" stroke-width="2" stroke-linecap="round"/>
1730
+ </symbol>
1731
+
1732
+ <!-- Info Icon -->
1733
+ <symbol id="icon-info" viewBox="0 0 24 24">
1734
+ <circle cx="12" cy="12" r="10" fill="none" stroke="currentColor" stroke-width="2"/>
1735
+ <path d="M12 16v-4M12 8h.01" stroke="currentColor" stroke-width="2" stroke-linecap="round"/>
1736
+ </symbol>
1737
+
1738
+ <!-- Market/Chart Icon -->
1739
+ <symbol id="icon-market" viewBox="0 0 24 24">
1740
+ <path d="M3 3v18h18" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
1741
+ <path d="M7 12l4-4 4 4 6-6" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
1742
+ </symbol>
1743
+
1744
+ <!-- Monitor/API Icon -->
1745
+ <symbol id="icon-monitor" viewBox="0 0 24 24">
1746
+ <rect x="2" y="3" width="20" height="14" rx="2" fill="none" stroke="currentColor" stroke-width="2"/>
1747
+ <path d="M8 21h8M12 17v4" stroke="currentColor" stroke-width="2" stroke-linecap="round"/>
1748
+ </symbol>
1749
+
1750
+ <!-- Advanced/Flash Icon -->
1751
+ <symbol id="icon-advanced" viewBox="0 0 24 24">
1752
+ <path d="M13 2L3 14h9l-1 8 10-12h-9l1-8z" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
1753
+ </symbol>
1754
+
1755
+ <!-- Settings/Gear Icon -->
1756
+ <symbol id="icon-settings" viewBox="0 0 24 24">
1757
+ <circle cx="12" cy="12" r="3" fill="none" stroke="currentColor" stroke-width="2"/>
1758
+ <path d="M12 1v6m0 6v6M5.64 5.64l4.24 4.24m4.24 4.24l4.24 4.24M1 12h6m6 0h6M5.64 18.36l4.24-4.24m4.24-4.24l4.24-4.24" stroke="currentColor" stroke-width="2" stroke-linecap="round"/>
1759
+ </symbol>
1760
+
1761
+ <!-- HuggingFace Icon -->
1762
+ <symbol id="icon-hf" viewBox="0 0 24 24">
1763
+ <path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2z" fill="none" stroke="currentColor" stroke-width="2"/>
1764
+ <path d="M8 12h8M12 8v8" stroke="currentColor" stroke-width="2" stroke-linecap="round"/>
1765
+ </symbol>
1766
+
1767
+ <!-- Pools/Refresh Icon -->
1768
+ <symbol id="icon-pools" viewBox="0 0 24 24">
1769
+ <path d="M21.5 2v6h-6M2.5 22v-6h6M2 11.5a10 10 0 0 1 18.8-4.3M22 12.5a10 10 0 0 1-18.8 4.2" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
1770
+ </symbol>
1771
+
1772
+ <!-- Logs/File Icon -->
1773
+ <symbol id="icon-logs" viewBox="0 0 24 24">
1774
+ <path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
1775
+ <path d="M14 2v6h6M16 13H8M16 17H8M10 9H8" stroke="currentColor" stroke-width="2" stroke-linecap="round"/>
1776
+ </symbol>
1777
+
1778
+ <!-- Resources/Box Icon -->
1779
+ <symbol id="icon-resources" viewBox="0 0 24 24">
1780
+ <path d="M21 16V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16z" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
1781
+ <path d="M3.27 6.96L12 12.01l8.73-5.05M12 22.08V12" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
1782
+ </symbol>
1783
+
1784
+ <!-- Reports/Chart Icon -->
1785
+ <symbol id="icon-reports" viewBox="0 0 24 24">
1786
+ <path d="M3 3v18h18" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
1787
+ <path d="M18 17V9M12 17V5M6 17v-3" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
1788
+ </symbol>
1789
+
1790
+ <!-- Search Icon -->
1791
+ <symbol id="icon-search" viewBox="0 0 24 24">
1792
+ <circle cx="11" cy="11" r="8" fill="none" stroke="currentColor" stroke-width="2"/>
1793
+ <path d="m21 21-4.35-4.35" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
1794
+ </symbol>
1795
+
1796
+ <!-- Refresh Icon -->
1797
+ <symbol id="icon-refresh" viewBox="0 0 24 24">
1798
+ <path d="M23 4v6h-6M1 20v-6h6M3.51 9a10 10 0 0 1 17.8-4.3M20.49 15a10 10 0 0 1-17.8 4.3" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
1799
+ </symbol>
1800
+
1801
+ <!-- Trending Up Icon -->
1802
+ <symbol id="icon-trending-up" viewBox="0 0 24 24">
1803
+ <path d="M23 6l-9.5 9.5-5-5L1 18" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
1804
+ <path d="M17 6h6v6" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
1805
+ </symbol>
1806
+
1807
+ <!-- Trending Down Icon -->
1808
+ <symbol id="icon-trending-down" viewBox="0 0 24 24">
1809
+ <path d="M23 18l-9.5-9.5-5 5L1 6" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
1810
+ <path d="M17 18h6v-6" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
1811
+ </symbol>
1812
+
1813
+ <!-- Volume Icon -->
1814
+ <symbol id="icon-volume" viewBox="0 0 24 24">
1815
+ <path d="M11 5L6 9H2v6h4l5 4V5z" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
1816
+ <path d="M19.07 4.93a10 10 0 0 1 0 14.14M15.54 8.46a5 5 0 0 1 0 7.07" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
1817
+ </symbol>
1818
+
1819
+ <!-- Diamond/Gem Icon -->
1820
+ <symbol id="icon-diamond" viewBox="0 0 24 24">
1821
+ <path d="M6 3h12l4 6-10 12L2 9l4-6z" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
1822
+ <path d="M11 3l1 18M13 3l-1 18M6 3l5 18M18 3l-5 18" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
1823
+ </symbol>
1824
+
1825
+ <!-- Fire/Trending Icon -->
1826
+ <symbol id="icon-fire" viewBox="0 0 24 24">
1827
+ <path d="M8.5 14.5A2.5 2.5 0 0 0 11 12c0-1.38-.5-2-1-3-1.072-2.143-.224-4.054 2-6 .5 2.5 2 4.9 4 6.5 2 1.6 3 3.5 3 5.5a7 7 0 1 1-14 0c0-1.153.433-2.294 1-3a2.5 2.5 0 0 0 2.5 2.5z" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
1828
+ </symbol>
1829
+
1830
+ <!-- Link/Chain Icon -->
1831
+ <symbol id="icon-link" viewBox="0 0 24 24">
1832
+ <path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
1833
+ <path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
1834
+ </symbol>
1835
+
1836
+ <!-- Export/Download Icon -->
1837
+ <symbol id="icon-export" viewBox="0 0 24 24">
1838
+ <path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
1839
+ <path d="M7 10l5 5 5-5M12 15V3" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
1840
+ </symbol>
1841
+
1842
+ <!-- Delete/Trash Icon -->
1843
+ <symbol id="icon-delete" viewBox="0 0 24 24">
1844
+ <path d="M3 6h18M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
1845
+ <path d="M10 11v6M14 11v6" stroke="currentColor" stroke-width="2" stroke-linecap="round"/>
1846
+ </symbol>
1847
+
1848
+ <!-- Brain/AI Icon -->
1849
+ <symbol id="icon-brain" viewBox="0 0 24 24">
1850
+ <path d="M9.5 2A2.5 2.5 0 0 1 12 4.5v15a2.5 2.5 0 0 1-4.96.44L2 22v-4a2.5 2.5 0 0 1 2.5-2.5h5z" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
1851
+ <path d="M14.5 2A2.5 2.5 0 0 0 12 4.5v15a2.5 2.5 0 0 0 4.96.44L22 22v-4a2.5 2.5 0 0 0-2.5-2.5h-5z" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
1852
+ </symbol>
1853
+
1854
+ <!-- Arrow Up Icon -->
1855
+ <symbol id="icon-arrow-up" viewBox="0 0 24 24">
1856
+ <path d="M12 19V5M5 12l7-7 7 7" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
1857
+ </symbol>
1858
+
1859
+ <!-- Live/Dot Icon -->
1860
+ <symbol id="icon-live" viewBox="0 0 24 24">
1861
+ <circle cx="12" cy="12" r="10" fill="currentColor"/>
1862
+ </symbol>
1863
+ </svg>
1864
  </head>
1865
 
1866
  <body>
 
1912
  </div>
1913
  </div>
1914
  <div class="header-actions">
1915
+ <div class="live-indicator">
1916
+ <span class="status-icon"><svg><use href="#icon-live"></use></svg></span>
1917
+ LIVE
1918
+ </div>
1919
  <div class="status-badge">
1920
  <div class="status-dot"></div>
1921
  <span id="statusText">All Systems Operational</span>
 
1925
 
1926
  <!-- Tabs -->
1927
  <div class="tabs">
1928
+ <button class="tab active" onclick="switchTab('market')">
1929
+ <span class="tab-icon"><svg><use href="#icon-market"></use></svg></span>
1930
+ Market
1931
+ </button>
1932
+ <button class="tab" onclick="switchTab('monitor')">
1933
+ <span class="tab-icon"><svg><use href="#icon-monitor"></use></svg></span>
1934
+ API Monitor
1935
+ </button>
1936
+ <button class="tab" onclick="switchTab('advanced')">
1937
+ <span class="tab-icon"><svg><use href="#icon-advanced"></use></svg></span>
1938
+ Advanced
1939
+ </button>
1940
+ <button class="tab" onclick="switchTab('admin')">
1941
+ <span class="tab-icon"><svg><use href="#icon-settings"></use></svg></span>
1942
+ Admin
1943
+ </button>
1944
+ <button class="tab" onclick="switchTab('hf')">
1945
+ <span class="tab-icon"><svg><use href="#icon-hf"></use></svg></span>
1946
+ HuggingFace
1947
+ </button>
1948
+ <button class="tab" onclick="switchTab('pools')">
1949
+ <span class="tab-icon"><svg><use href="#icon-pools"></use></svg></span>
1950
+ Pools
1951
+ </button>
1952
+ <button class="tab" onclick="switchTab('logs')">
1953
+ <span class="tab-icon"><svg><use href="#icon-logs"></use></svg></span>
1954
+ Logs
1955
+ </button>
1956
+ <button class="tab" onclick="switchTab('resources')">
1957
+ <span class="tab-icon"><svg><use href="#icon-resources"></use></svg></span>
1958
+ Resources
1959
+ </button>
1960
+ <button class="tab" onclick="switchTab('reports')">
1961
+ <span class="tab-icon"><svg><use href="#icon-reports"></use></svg></span>
1962
+ Reports
1963
+ </button>
1964
  </div>
1965
  </div>
1966
 
 
2064
  <!-- Market Table -->
2065
  <div class="market-section">
2066
  <div class="section-header">
2067
+ <div class="section-title gradient-text">
2068
+ <span class="icon icon-md" style="margin-left: 8px;"><svg><use href="#icon-diamond"></use></svg></span>
2069
+ Live Market Data
2070
+ </div>
2071
+ <button class="refresh-btn ripple" onclick="loadMarketData()" data-tooltip="به‌روزرسانی داده‌های بازار">
2072
+ <span class="icon icon-sm"><svg><use href="#icon-refresh"></use></svg></span>
2073
+ Refresh
2074
+ </button>
2075
  </div>
2076
 
2077
  <!-- Search Bar -->
2078
  <div class="search-container">
2079
+ <span class="search-icon icon"><svg><use href="#icon-search"></use></svg></span>
2080
  <input type="text" class="search-input" id="marketSearch" placeholder="جستجوی ارز دیجیتال (مثال: Bitcoin, BTC, Ethereum)..." oninput="filterMarketTable()">
2081
  </div>
2082
 
 
2084
  <div class="filter-chips">
2085
  <button class="filter-chip active" onclick="filterByCategory('all')">همه</button>
2086
  <button class="filter-chip" onclick="filterByCategory('top10')">Top 10</button>
2087
+ <button class="filter-chip" onclick="filterByCategory('gainers')">
2088
+ <span class="icon icon-sm status-icon-success"><svg><use href="#icon-trending-up"></use></svg></span>
2089
+ در حال رشد
2090
+ </button>
2091
+ <button class="filter-chip" onclick="filterByCategory('losers')">
2092
+ <span class="icon icon-sm status-icon-error"><svg><use href="#icon-trending-down"></use></svg></span>
2093
+ در حال سقوط
2094
+ </button>
2095
+ <button class="filter-chip" onclick="filterByCategory('volume')">
2096
+ <span class="icon icon-sm"><svg><use href="#icon-volume"></use></svg></span>
2097
+ حجم بالا
2098
+ </button>
2099
  </div>
2100
  <div style="overflow-x: auto;">
2101
  <table id="marketTable">
 
2144
 
2145
  <!-- Trending Section -->
2146
  <div class="market-section">
2147
+ <div class="section-title" style="margin-bottom: 20px;">
2148
+ <span class="icon icon-md" style="margin-left: 8px;"><svg><use href="#icon-fire"></use></svg></span>
2149
+ Trending Now
2150
+ </div>
2151
  <div id="trendingGrid"
2152
  style="display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 15px;">
2153
  <div class="loading">
 
2226
 
2227
  <div class="market-section">
2228
  <div class="section-header">
2229
+ <div class="section-title">
2230
+ <span class="icon icon-md" style="margin-left: 8px;"><svg><use href="#icon-monitor"></use></svg></span>
2231
+ API Providers Status
2232
+ </div>
2233
+ <button class="refresh-btn ripple" onclick="loadMonitorData()">
2234
+ <span class="icon icon-sm"><svg><use href="#icon-refresh"></use></svg></span>
2235
+ Refresh
2236
+ </button>
2237
  </div>
2238
  <div style="overflow-x: auto;">
2239
  <table>
 
2256
  </div>
2257
 
2258
  <div class="market-section">
2259
+ <div class="section-title" style="margin-bottom: 20px;">
2260
+ <span class="icon icon-md" style="margin-left: 8px;"><svg><use href="#icon-brain"></use></svg></span>
2261
+ HuggingFace Sentiment Analysis
2262
+ </div>
2263
  <div class="form-group">
2264
  <label class="form-label">Enter crypto-related text (one per line):</label>
2265
  <textarea class="form-textarea" id="sentimentText" rows="5"
 
2267
  ETH looks weak
2268
  Market is bullish today</textarea>
2269
  </div>
2270
+ <button class="refresh-btn ripple" onclick="runSentiment()">
2271
+ <span class="icon icon-sm"><svg><use href="#icon-brain"></use></svg></span>
2272
+ Analyze Sentiment
2273
+ </button>
2274
  <div id="sentimentResult"
2275
  style="margin-top: 20px; padding: 20px; background: rgba(17, 24, 39, 0.6); border-radius: 12px; text-align: center; font-size: 36px; font-weight: 900;">
2276
  —</div>
 
2404
  </div>
2405
 
2406
  <div class="market-section">
2407
+ <div class="section-title" style="margin-bottom: 20px;">
2408
+ <span class="icon icon-md" style="margin-left: 8px;"><svg><use href="#icon-logs"></use></svg></span>
2409
+ Current API Sources
2410
+ </div>
2411
  <div id="apisList">Loading...</div>
2412
  </div>
2413
 
2414
  <div class="market-section">
2415
+ <div class="section-title" style="margin-bottom: 20px;">
2416
+ <span class="icon icon-md" style="margin-left: 8px;"><svg><use href="#icon-settings"></use></svg></span>
2417
+ Settings
2418
+ </div>
2419
  <div class="form-group">
2420
  <label class="form-label">API Check Interval (seconds)</label>
2421
  <input type="number" class="form-input" id="checkInterval" value="30" min="10" max="300">
 
2428
  </div>
2429
 
2430
  <div class="market-section">
2431
+ <div class="section-title" style="margin-bottom: 20px;">
2432
+ <span class="icon icon-md" style="margin-left: 8px;"><svg><use href="#icon-reports"></use></svg></span>
2433
+ Statistics
2434
+ </div>
2435
  <div class="stats-grid">
2436
  <div class="stat-card">
2437
  <div class="stat-value" id="statTotal">0</div>
 
2453
  <div id="tab-hf" class="tab-content">
2454
  <div class="market-section">
2455
  <div class="section-header">
2456
+ <div class="section-title">
2457
+ <span class="icon icon-md" style="margin-left: 8px;"><svg><use href="#icon-reports"></use></svg></span>
2458
+ Health Status
2459
+ </div>
2460
+ <button class="refresh-btn ripple" onclick="loadHFHealth()">
2461
+ <span class="icon icon-sm"><svg><use href="#icon-refresh"></use></svg></span>
2462
+ Refresh
2463
+ </button>
2464
  </div>
2465
  <pre id="healthOutput"
2466
  style="background: #1e293b; color: #e2e8f0; padding: 15px; border-radius: 8px; overflow-x: auto; font-size: 12px; max-height: 200px; overflow-y: auto;">Loading...</pre>
 
2505
  </div>
2506
 
2507
  <div class="market-section">
2508
+ <div class="section-title" style="margin-bottom: 20px;">
2509
+ <span class="icon icon-md"><svg><use href="#icon-brain"></use></svg></span>
2510
+ Sentiment Analysis
2511
+ </div>
2512
  <div class="form-group">
2513
  <label class="form-label">Enter text samples (one per line):</label>
2514
  <textarea class="form-textarea" id="sentimentTexts" rows="5"
 
2516
  ETH looks weak
2517
  Crypto market is bullish today</textarea>
2518
  </div>
2519
+ <button class="refresh-btn ripple" onclick="doSentiment()">
2520
+ <span class="icon icon-sm"><svg><use href="#icon-brain"></use></svg></span>
2521
+ Run Sentiment Analysis
2522
+ </button>
2523
  <div id="voteDisplay"
2524
  style="margin-top: 20px; padding: 20px; background: rgba(17, 24, 39, 0.6); border-radius: 12px; text-align: center; font-size: 36px; font-weight: 900;">
2525
  —</div>
 
2532
  <div id="tab-logs" class="tab-content">
2533
  <div class="market-section">
2534
  <div class="section-header">
2535
+ <div class="section-title">
2536
+ <span class="icon icon-md"><svg><use href="#icon-logs"></use></svg></span>
2537
+ Log Management
2538
+ </div>
2539
  <div style="display: flex; gap: 10px;">
2540
+ <button class="refresh-btn ripple" onclick="loadLogs()">
2541
+ <span class="icon icon-sm"><svg><use href="#icon-refresh"></use></svg></span>
2542
+ Refresh
2543
+ </button>
2544
+ <button class="refresh-btn ripple" onclick="exportLogsJSON()"
2545
+ style="background: rgba(16, 185, 129, 0.2); color: var(--accent-green);">
2546
+ <span class="icon icon-sm"><svg><use href="#icon-export"></use></svg></span>
2547
+ Export JSON
2548
+ </button>
2549
+ <button class="refresh-btn ripple" onclick="exportLogsCSV()"
2550
+ style="background: rgba(16, 185, 129, 0.2); color: var(--accent-green);">
2551
+ <span class="icon icon-sm"><svg><use href="#icon-reports"></use></svg></span>
2552
+ Export CSV
2553
+ </button>
2554
+ <button class="refresh-btn ripple" onclick="clearAllLogs()"
2555
+ style="background: rgba(239, 68, 68, 0.2); color: var(--accent-red);">
2556
+ <span class="icon icon-sm"><svg><use href="#icon-delete"></use></svg></span>
2557
+ Clear
2558
+ </button>
2559
  </div>
2560
  </div>
2561
 
 
2738
 
2739
  <!-- Reports Tab -->
2740
  <div id="tab-reports" class="tab-content">
2741
+ <!-- System Status Alerts -->
2742
+ <div class="market-section" id="systemAlertsSection" style="display: none;">
2743
+ <div class="section-header">
2744
+ <div class="section-title">
2745
+ <span class="icon icon-md status-icon-warning"><svg><use href="#icon-warning"></use></svg></span>
2746
+ System Status & Alerts
2747
+ </div>
2748
+ <button class="refresh-btn ripple" onclick="loadSystemAlerts()">
2749
+ <span class="icon icon-sm"><svg><use href="#icon-refresh"></use></svg></span>
2750
+ Refresh
2751
+ </button>
2752
+ </div>
2753
+ <div id="systemAlertsContainer"></div>
2754
+ </div>
2755
+
2756
  <div class="market-section">
2757
  <div class="section-header">
2758
+ <div class="section-title">
2759
+ <span class="icon icon-md"><svg><use href="#icon-search"></use></svg></span>
2760
+ System Diagnostics
2761
+ </div>
2762
  <div style="display: flex; gap: 10px;">
2763
+ <button class="refresh-btn ripple" onclick="runDiagnostics(false)"
2764
+ style="background: rgba(59, 130, 246, 0.2); color: var(--accent-blue);">
2765
+ <span class="icon icon-sm"><svg><use href="#icon-search"></use></svg></span>
2766
+ بررسی
2767
+ </button>
2768
+ <button class="refresh-btn ripple" onclick="runDiagnostics(true)"
2769
+ style="background: rgba(16, 185, 129, 0.2); color: var(--accent-green);">
2770
+ <span class="icon icon-sm"><svg><use href="#icon-settings"></use></svg></span>
2771
+ بررسی و تعمیر
2772
+ </button>
2773
+ <button class="refresh-btn ripple" onclick="loadReports()">
2774
+ <span class="icon icon-sm"><svg><use href="#icon-refresh"></use></svg></span>
2775
+ به‌روزرسانی
2776
+ </button>
2777
  </div>
2778
  </div>
2779
 
 
2787
 
2788
  <div class="market-section">
2789
  <div class="section-header">
2790
+ <div class="section-title">
2791
+ <span class="icon icon-md"><svg><use href="#icon-pools"></use></svg></span>
2792
+ Auto-Discovery Service Report
2793
+ </div>
2794
+ <button class="refresh-btn ripple" onclick="loadDiscoveryReport()">
2795
+ <span class="icon icon-sm"><svg><use href="#icon-refresh"></use></svg></span>
2796
+ به‌روزرسانی
2797
+ </button>
2798
  </div>
2799
  <div id="discoveryReport">
2800
  <div class="loading">
 
2805
 
2806
  <div class="market-section">
2807
  <div class="section-header">
2808
+ <div class="section-title">
2809
+ <span class="icon icon-md"><svg><use href="#icon-brain"></use></svg></span>
2810
+ HuggingFace Models Status Report
2811
+ </div>
2812
+ <button class="refresh-btn ripple" onclick="loadModelsReport()">
2813
+ <span class="icon icon-sm"><svg><use href="#icon-refresh"></use></svg></span>
2814
+ به‌روزرسانی
2815
+ </button>
2816
  </div>
2817
  <div id="modelsReport">
2818
  <div class="loading">
 
3045
 
3046
  // Call updateStats with validated data - double check before calling
3047
  if (stats && stats.market && typeof stats.market === 'object' && !Array.isArray(stats.market)) {
3048
+ updateStats(stats, sentiment);
3049
  } else {
3050
  console.error('Failed final validation before updateStats:', { stats, sentiment });
3051
  throw new Error('داده‌های stats.market نامعتبر است');
 
3138
  if (sentimentLabelEl) {
3139
  sentimentLabelEl.innerHTML = `<span>${classification}</span>`;
3140
 
3141
+ if (fg < 25) {
3142
  sentimentLabelEl.style.color = 'var(--accent-red)';
3143
+ } else if (fg < 45) {
3144
  sentimentLabelEl.style.color = 'var(--accent-yellow)';
3145
+ } else if (fg < 55) {
3146
  sentimentLabelEl.style.color = 'var(--text-secondary)';
3147
+ } else if (fg < 75) {
3148
  sentimentLabelEl.style.color = 'var(--accent-blue)';
3149
+ } else {
3150
  sentimentLabelEl.style.color = 'var(--accent-green)';
3151
  }
3152
  }
 
3160
  function updateMarketTable(cryptos) {
3161
  try {
3162
  if (!cryptos || !Array.isArray(cryptos) || cryptos.length === 0) {
3163
+ const tbody = document.getElementById('marketTableBody');
3164
  if (tbody) {
3165
  tbody.innerHTML = '<tr><td colspan="6" style="text-align: center; padding: 40px; color: var(--text-secondary);">هیچ داده‌ای یافت نشد</td></tr>';
3166
  }
 
3185
 
3186
  return `
3187
  <tr data-name="${name.toLowerCase()}" data-symbol="${symbol.toLowerCase()}" data-change="${change24h}" data-rank="${crypto.rank || index + 1}">
3188
+ <td style="font-weight: 700; color: var(--text-secondary);">${crypto.rank || index + 1}</td>
3189
+ <td>
3190
+ <div class="crypto-name">
3191
  ${crypto.image ? `<img src="${crypto.image}" class="crypto-img" alt="${symbol}" onerror="this.style.display='none'">` :
3192
  `<div class="crypto-img" style="background: linear-gradient(135deg, #3b82f6, #8b5cf6); display: flex; align-items: center; justify-content: center; font-weight: 700; color: white;">${symbol[0] || '?'}</div>`}
3193
+ <div>
3194
  <div style="font-weight: 600;">${name}</div>
3195
  <div class="crypto-symbol">${symbol}</div>
3196
+ </div>
3197
+ </div>
3198
+ </td>
3199
  <td class="price number-counter">$${price.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 6 })}</td>
3200
  <td><span class="change ${changeClass} pulse-data">${changeIcon} ${change24h >= 0 ? '+' : ''}${change24h.toFixed(2)}%</span></td>
3201
  <td style="font-weight: 600;">$${(marketCap / 1e9).toFixed(2)}B</td>
3202
  <td style="color: var(--text-secondary);">$${(volume24h / 1e9).toFixed(2)}B</td>
3203
+ </tr>
3204
  `;
3205
  }).join('');
3206
  } catch (error) {
 
3214
 
3215
  function updateTrending(trending) {
3216
  try {
3217
+ const grid = document.getElementById('trendingGrid');
3218
  if (!grid) return;
3219
 
3220
  if (!trending || !Array.isArray(trending) || trending.length === 0) {
 
3226
  const name = coin.name || 'نامشخص';
3227
  const symbol = coin.symbol || 'N/A';
3228
  return `
3229
+ <div style="background: rgba(59, 130, 246, 0.1); border: 1px solid rgba(59, 130, 246, 0.2); border-radius: 12px; padding: 15px; display: flex; align-items: center; gap: 12px;">
3230
+ <div style="font-size: 20px; font-weight: 900; color: var(--accent-yellow);">#${index + 1}</div>
3231
  ${coin.thumb ? `<img src="${coin.thumb}" style="width: 32px; height: 32px; border-radius: 8px;" onerror="this.style.display='none'">` : ''}
3232
+ <div>
3233
  <div style="font-weight: 600;">${name}</div>
3234
  <div style="font-size: 12px; color: var(--text-secondary);">${symbol}</div>
3235
+ </div>
3236
+ </div>
3237
  `;
3238
  }).join('');
3239
  } catch (error) {
 
3247
 
3248
  function updateDeFi(defi) {
3249
  try {
3250
+ const list = document.getElementById('defiList');
3251
  if (!list) return;
3252
 
3253
  const protocols = defi && defi.protocols ? defi.protocols : [];
3254
  const totalTvl = defi && defi.total_tvl ? defi.total_tvl : 0;
3255
 
3256
+ list.innerHTML = `
3257
  <div class="stat-card" style="margin-bottom: 20px; text-align: center; background: linear-gradient(135deg, rgba(59, 130, 246, 0.2), rgba(139, 92, 246, 0.2));">
3258
  <div class="stat-value gradient-text" style="font-size: 42px; margin-bottom: 8px;">$${(totalTvl / 1e9).toFixed(2)}B</div>
3259
  <div class="stat-label" style="font-size: 16px;">Total Value Locked</div>
3260
+ </div>
3261
+ <div style="display: grid; gap: 12px;">
3262
  ${protocols.length > 0 ? protocols.map((p, i) => {
3263
  const name = p.name || 'نامشخص';
3264
  const chain = p.chain || 'N/A';
 
3268
  return `
3269
  <div class="stat-card" style="animation-delay: ${i * 0.05}s; cursor: pointer;" onclick="showToast('${name}: $${(tvl / 1e9).toFixed(2)}B TVL', 'info', 'DeFi Protocol')">
3270
  <div style="display: flex; justify-content: space-between; align-items: center;">
3271
+ <div>
3272
  <div style="font-weight: 700; font-size: 16px; margin-bottom: 4px;">${i + 1}. ${name}</div>
3273
  <div style="font-size: 12px; color: var(--text-secondary); display: flex; align-items: center; gap: 6px;">
3274
  <span>🔗</span> <span>${chain}</span>
3275
  </div>
3276
+ </div>
3277
+ <div style="text-align: right;">
3278
  <div class="stat-value" style="font-size: 18px; margin-bottom: 4px;">$${(tvl / 1e9).toFixed(2)}B</div>
3279
  <div class="stat-change ${changeClass}" style="font-size: 13px;">
3280
  ${change24h >= 0 ? '📈' : '📉'} ${change24h >= 0 ? '+' : ''}${change24h.toFixed(2)}%
 
 
 
3281
  </div>
3282
+ </div>
3283
+ </div>
3284
+ </div>
3285
+ `;
3286
  }).join('') : '<div class="empty-state"><div class="empty-state-icon">📦</div><div>هیچ پروتکلی یافت نشد</div></div>'}
3287
  </div>
3288
  `;
 
3379
  window.wsClient.on('stats_update', (message) => {
3380
  console.log('📊 Stats update:', message.data);
3381
  if (typeof updateOnlineStats === 'function') {
3382
+ updateOnlineStats(message.data);
3383
  }
3384
  });
3385
 
 
3407
  // درخواست آمار هر 10 ثانیه (فقط یک بار تنظیم شود)
3408
  if (!wsStatsInterval) {
3409
  wsStatsInterval = setInterval(() => {
3410
+ if (window.wsClient && window.wsClient.isConnected) {
3411
+ window.wsClient.requestStats();
3412
+ }
3413
+ }, 10000);
3414
  }
3415
  } else {
3416
  wsConnectAttempts++;
 
3419
  if (wsConnectAttempts % 5 === 0 || wsConnectAttempts === 1) {
3420
  console.log(`⏳ در انتظار WebSocket Client... (${wsConnectAttempts}/${MAX_WS_CONNECT_ATTEMPTS})`);
3421
  }
3422
+ setTimeout(connectWebSocket, 1000);
3423
  } else {
3424
  console.warn('⚠️ WebSocket Client پس از ' + MAX_WS_CONNECT_ATTEMPTS + ' تلاش آماده نشد. ممکن است فایل websocket-client.js لود نشده باشد یا WebSocket پشتیبانی نشود.');
3425
  console.warn('⚠️ بررسی کنید که فایل /static/js/websocket-client.js به درستی لود شده باشد.');
 
3513
  if (providers.length === 0) {
3514
  tbody.innerHTML = '<tr><td colspan="5" style="text-align: center; padding: 40px; color: var(--text-secondary);">هیچ APIای یافت نشد</td></tr>';
3515
  } else {
3516
+ tbody.innerHTML = providers.map(p => {
3517
+ let statusClass = 'badge-success';
3518
+ if (p.status === 'offline') statusClass = 'badge-danger';
3519
+ else if (p.status === 'degraded') statusClass = 'badge-warning';
3520
 
3521
+ return `
3522
+ <tr>
3523
  <td><strong>${p.name || 'نامشخص'}</strong></td>
3524
  <td><span class="badge badge-info">${p.category || 'نامشخص'}</span></td>
3525
  <td><span class="badge ${statusClass}">${(p.status || 'unknown').toUpperCase()}</span></td>
3526
  <td>${p.response_time_ms || p.avg_response_time_ms || 0}ms</td>
3527
  <td style="color: var(--text-secondary); font-size: 13px;">${p.last_fetch ? new Date(p.last_fetch).toLocaleTimeString() : 'نامشخص'}</td>
3528
+ </tr>
3529
+ `;
3530
+ }).join('');
3531
  }
3532
  }
3533
  } catch (error) {
 
4224
  // Auto hide after 3 seconds
4225
  setTimeout(() => {
4226
  hideFeedback();
4227
+ }, 3000);
4228
  }
4229
  }
4230
 
 
4655
  ]);
4656
  }
4657
 
4658
+ // Load System Alerts
4659
+ async function loadSystemAlerts() {
4660
+ try {
4661
+ const response = await fetch('/api/diagnostics/last');
4662
+ const report = await response.json();
4663
+
4664
+ if (report.message || !report.issues || report.issues.length === 0) {
4665
+ document.getElementById('systemAlertsSection').style.display = 'none';
4666
+ return;
4667
+ }
4668
+
4669
+ displaySystemAlerts(report.issues);
4670
+ document.getElementById('systemAlertsSection').style.display = 'block';
4671
+ } catch (error) {
4672
+ console.error('Error loading system alerts:', error);
4673
+ }
4674
+ }
4675
+
4676
+ function displaySystemAlerts(issues) {
4677
+ const container = document.getElementById('systemAlertsContainer');
4678
+ if (!container) return;
4679
+
4680
+ const severityConfig = {
4681
+ 'critical': {
4682
+ icon: 'icon-error',
4683
+ color: 'var(--accent-red)',
4684
+ bg: 'rgba(239, 68, 68, 0.1)',
4685
+ border: 'rgba(239, 68, 68, 0.3)'
4686
+ },
4687
+ 'warning': {
4688
+ icon: 'icon-warning',
4689
+ color: 'var(--accent-yellow)',
4690
+ bg: 'rgba(245, 158, 11, 0.1)',
4691
+ border: 'rgba(245, 158, 11, 0.3)'
4692
+ },
4693
+ 'info': {
4694
+ icon: 'icon-info',
4695
+ color: 'var(--accent-blue)',
4696
+ bg: 'rgba(59, 130, 246, 0.1)',
4697
+ border: 'rgba(59, 130, 246, 0.3)'
4698
+ }
4699
+ };
4700
+
4701
+ const solutions = {
4702
+ 'HF_API_TOKEN': {
4703
+ title: 'تنظیم متغیر محیطی HF_API_TOKEN',
4704
+ steps: [
4705
+ '1. یک توکن از HuggingFace دریافت کنید:',
4706
+ ' - به https://huggingface.co/settings/tokens بروید',
4707
+ ' - یک توکن جدید ایجاد کنید',
4708
+ '2. توکن را به متغیر محیطی اضافه کنید:',
4709
+ ' Windows: set HF_API_TOKEN=your_token_here',
4710
+ ' Linux/Mac: export HF_API_TOKEN=your_token_here',
4711
+ ' یا در فایل .env: HF_API_TOKEN=your_token_here'
4712
+ ]
4713
+ },
4714
+ 'resources.json': {
4715
+ title: 'ایجاد فایل resources.json',
4716
+ steps: [
4717
+ 'این فایل به صورت خودکار ساخته می‌شود.',
4718
+ 'اگر نیاز به تنظیمات دستی دارید، می‌توانید آن را ایجاد کنید:',
4719
+ '{',
4720
+ ' "resources": []',
4721
+ '}'
4722
+ ]
4723
+ },
4724
+ 'config.json': {
4725
+ title: 'ایجاد فایل config.json',
4726
+ steps: [
4727
+ 'این فایل به صورت خودکار ساخته می‌شود.',
4728
+ 'اگر نیاز به تنظیمات دستی دارید، می‌توانید آن را ایجاد کنید.'
4729
+ ]
4730
+ },
4731
+ 'HuggingFace API': {
4732
+ title: 'رفع مشکل اتصال به HuggingFace',
4733
+ steps: [
4734
+ '1. بررسی اتصال اینترنت',
4735
+ '2. بررسی فایروال و پروکسی',
4736
+ '3. بررسی DNS settings',
4737
+ '4. اگر از VPN استفاده می‌کنید، آن را غیرفعال کنید',
4738
+ '5. بررسی کنید که https://api.huggingface.co قابل دسترسی باشد'
4739
+ ]
4740
+ },
4741
+ 'Auto-Discovery': {
4742
+ title: 'فعال‌سازی Auto-Discovery Service',
4743
+ steps: [
4744
+ 'برای فعال‌سازی سرویس Auto-Discovery:',
4745
+ '1. متغیر محیطی را تنظیم کنید:',
4746
+ ' export ENABLE_AUTO_DISCOVERY=true',
4747
+ '2. یا در فایل .env اضافه کنید:',
4748
+ ' ENABLE_AUTO_DISCOVERY=true',
4749
+ '3. سرور را restart کنید'
4750
+ ]
4751
+ }
4752
+ };
4753
+
4754
+ let html = '';
4755
+ issues.forEach((issue, index) => {
4756
+ const config = severityConfig[issue.severity] || severityConfig['info'];
4757
+ const solutionKey = issue.title.includes('HF_API_TOKEN') ? 'HF_API_TOKEN' :
4758
+ issue.title.includes('resources.json') ? 'resources.json' :
4759
+ issue.title.includes('config.json') ? 'config.json' :
4760
+ issue.title.includes('HuggingFace') ? 'HuggingFace API' :
4761
+ issue.title.includes('Auto-Discovery') ? 'Auto-Discovery' : null;
4762
+
4763
+ const solution = solutionKey ? solutions[solutionKey] : null;
4764
+
4765
+ html += `
4766
+ <div class="stat-card" style="margin-bottom: 15px; border-left: 4px solid ${config.border}; background: ${config.bg}; animation-delay: ${index * 0.1}s;">
4767
+ <div style="display: flex; align-items: start; gap: 12px;">
4768
+ <div class="icon icon-md status-icon-${issue.severity}" style="flex-shrink: 0; margin-top: 2px;">
4769
+ <svg><use href="#${config.icon}"></use></svg>
4770
+ </div>
4771
+ <div style="flex: 1;">
4772
+ <div style="display: flex; justify-content: space-between; align-items: start; margin-bottom: 8px;">
4773
+ <div>
4774
+ <h3 style="font-size: 16px; font-weight: 700; margin-bottom: 4px; color: ${config.color};">
4775
+ ${issue.title}
4776
+ </h3>
4777
+ <div style="font-size: 13px; color: var(--text-secondary); margin-bottom: 8px;">
4778
+ ${issue.description}
4779
+ </div>
4780
+ </div>
4781
+ <span class="badge badge-${issue.severity === 'critical' ? 'danger' : issue.severity === 'warning' ? 'warning' : 'info'}" style="flex-shrink: 0;">
4782
+ ${issue.category}
4783
+ </span>
4784
+ </div>
4785
+
4786
+ ${solution ? `
4787
+ <div style="margin-top: 12px; padding: 12px; background: rgba(17, 24, 39, 0.6); border-radius: 8px; border: 1px solid var(--border);">
4788
+ <div style="display: flex; align-items: center; gap: 8px; margin-bottom: 8px;">
4789
+ <span class="icon icon-sm status-icon-info"><svg><use href="#icon-info"></use></svg></span>
4790
+ <strong style="font-size: 14px;">راه‌حل:</strong>
4791
+ </div>
4792
+ <div style="font-size: 12px; color: var(--text-secondary); font-family: 'Courier New', monospace; line-height: 1.8;">
4793
+ ${solution.steps.map(step => `<div style="margin-bottom: 4px;">${step}</div>`).join('')}
4794
+ </div>
4795
+ </div>
4796
+ ` : ''}
4797
+
4798
+ <div style="margin-top: 8px; font-size: 11px; color: var(--text-secondary);">
4799
+ ${new Date(issue.timestamp).toLocaleString('fa-IR')}
4800
+ </div>
4801
+ </div>
4802
+ </div>
4803
+ </div>
4804
+ `;
4805
+ });
4806
+
4807
+ container.innerHTML = html || '<div style="text-align: center; padding: 40px; color: var(--text-secondary);">هیچ هشداری یافت نشد</div>';
4808
+ }
4809
+
4810
  async function runDiagnostics(autoFix = false) {
4811
  const resultsDiv = document.getElementById('diagnosticsResults');
4812
  resultsDiv.innerHTML = '<div class="loading"><div class="spinner"></div></div>';
 
4818
  const report = await response.json();
4819
 
4820
  displayDiagnosticsReport(report);
4821
+ showToast(`اشکال‌یابی انجام شد (${report.total_issues} مشکل یافت شد)`, 'success', 'Diagnostics');
4822
+
4823
+ // Update system alerts
4824
+ if (report.issues && report.issues.length > 0) {
4825
+ displaySystemAlerts(report.issues);
4826
+ document.getElementById('systemAlertsSection').style.display = 'block';
4827
+ }
4828
  } catch (error) {
4829
+ resultsDiv.innerHTML = `<div class="alert alert-error">
4830
+ <span class="icon icon-md status-icon-error"><svg><use href="#icon-error"></use></svg></span>
4831
+ خطا: ${error.message}
4832
+ </div>`;
4833
+ showToast('خطا در اجرای اشکال‌یابی', 'error', 'Error');
4834
  }
4835
  }
4836
 
 
4944
  }
4945
 
4946
  displayDiagnosticsReport(report);
4947
+
4948
+ // Load system alerts
4949
+ if (report.issues && report.issues.length > 0) {
4950
+ displaySystemAlerts(report.issues);
4951
+ document.getElementById('systemAlertsSection').style.display = 'block';
4952
+ }
4953
  } catch (error) {
4954
  console.error('Error loading last diagnostics:', error);
4955
  }