Upload 47 files
Browse files- index.html +5 -5
- static/css/main.css +18 -18
- static/js/app.js +28 -7
index.html
CHANGED
|
@@ -14,11 +14,11 @@
|
|
| 14 |
<script src="https://cdn.jsdelivr.net/npm/chart.js@4.4.0/dist/chart.umd.min.js"></script>
|
| 15 |
|
| 16 |
<!-- Styles -->
|
| 17 |
-
<link rel="stylesheet" href="/static/css/main.css?v=
|
| 18 |
-
<link rel="stylesheet" href="/static/css/toast.css?v=
|
| 19 |
-
<script src="/static/js/trading-pairs-loader.js?v=
|
| 20 |
-
<script src="/static/js/toast.js?v=
|
| 21 |
-
<script src="/static/js/app.js?v=
|
| 22 |
|
| 23 |
<!-- Favicon -->
|
| 24 |
<link rel="icon" href="data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 100 100%22><text y=%22.9em%22 font-size=%2290%22>🚀</text></svg>">
|
|
|
|
| 14 |
<script src="https://cdn.jsdelivr.net/npm/chart.js@4.4.0/dist/chart.umd.min.js"></script>
|
| 15 |
|
| 16 |
<!-- Styles -->
|
| 17 |
+
<link rel="stylesheet" href="/static/css/main.css?v=4">
|
| 18 |
+
<link rel="stylesheet" href="/static/css/toast.css?v=4">
|
| 19 |
+
<script src="/static/js/trading-pairs-loader.js?v=4" defer></script>
|
| 20 |
+
<script src="/static/js/toast.js?v=4" defer></script>
|
| 21 |
+
<script src="/static/js/app.js?v=4" defer></script>
|
| 22 |
|
| 23 |
<!-- Favicon -->
|
| 24 |
<link rel="icon" href="data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 100 100%22><text y=%22.9em%22 font-size=%2290%22>🚀</text></svg>">
|
static/css/main.css
CHANGED
|
@@ -33,8 +33,8 @@
|
|
| 33 |
--glow: 0 0 20px rgba(102, 126, 234, 0.3);
|
| 34 |
|
| 35 |
/* Sidebar */
|
| 36 |
-
--sidebar-width:
|
| 37 |
-
--sidebar-collapsed-width:
|
| 38 |
|
| 39 |
/* Gradients */
|
| 40 |
--gradient-purple: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
|
@@ -114,7 +114,7 @@ body::before {
|
|
| 114 |
}
|
| 115 |
|
| 116 |
.sidebar-header {
|
| 117 |
-
padding:
|
| 118 |
border-bottom: 1px solid var(--border);
|
| 119 |
display: flex;
|
| 120 |
justify-content: space-between;
|
|
@@ -124,7 +124,7 @@ body::before {
|
|
| 124 |
.sidebar-logo {
|
| 125 |
display: flex;
|
| 126 |
align-items: center;
|
| 127 |
-
gap:
|
| 128 |
transition: var(--transition-normal);
|
| 129 |
}
|
| 130 |
|
|
@@ -134,10 +134,10 @@ body::before {
|
|
| 134 |
}
|
| 135 |
|
| 136 |
.sidebar-logo .logo-icon {
|
| 137 |
-
width:
|
| 138 |
-
height:
|
| 139 |
background: var(--gradient-purple);
|
| 140 |
-
border-radius:
|
| 141 |
display: flex;
|
| 142 |
align-items: center;
|
| 143 |
justify-content: center;
|
|
@@ -153,7 +153,7 @@ body::before {
|
|
| 153 |
}
|
| 154 |
|
| 155 |
.sidebar-logo .logo-text h1 {
|
| 156 |
-
font-size:
|
| 157 |
font-weight: 800;
|
| 158 |
background: linear-gradient(135deg, var(--primary), var(--secondary));
|
| 159 |
-webkit-background-clip: text;
|
|
@@ -163,7 +163,7 @@ body::before {
|
|
| 163 |
}
|
| 164 |
|
| 165 |
.sidebar-logo .logo-text p {
|
| 166 |
-
font-size:
|
| 167 |
color: var(--text-secondary);
|
| 168 |
font-weight: 500;
|
| 169 |
}
|
|
@@ -188,31 +188,31 @@ body::before {
|
|
| 188 |
/* Sidebar Navigation */
|
| 189 |
.sidebar-nav {
|
| 190 |
flex: 1;
|
| 191 |
-
padding:
|
| 192 |
overflow-y: auto;
|
| 193 |
}
|
| 194 |
|
| 195 |
.nav-item {
|
| 196 |
display: flex;
|
| 197 |
align-items: center;
|
| 198 |
-
gap:
|
| 199 |
-
padding: 14px
|
| 200 |
background: transparent;
|
| 201 |
border: 1px solid transparent;
|
| 202 |
-
border-radius:
|
| 203 |
color: var(--text-secondary);
|
| 204 |
cursor: pointer;
|
| 205 |
-
font-size:
|
| 206 |
font-weight: 600;
|
| 207 |
transition: all var(--transition-fast);
|
| 208 |
width: 100%;
|
| 209 |
text-align: left;
|
| 210 |
-
margin-bottom:
|
| 211 |
}
|
| 212 |
|
| 213 |
.nav-item svg {
|
| 214 |
-
width:
|
| 215 |
-
height:
|
| 216 |
flex-shrink: 0;
|
| 217 |
stroke-width: 2;
|
| 218 |
}
|
|
@@ -233,7 +233,7 @@ body::before {
|
|
| 233 |
|
| 234 |
/* Sidebar Footer */
|
| 235 |
.sidebar-footer {
|
| 236 |
-
padding:
|
| 237 |
border-top: 1px solid var(--border);
|
| 238 |
}
|
| 239 |
|
|
|
|
| 33 |
--glow: 0 0 20px rgba(102, 126, 234, 0.3);
|
| 34 |
|
| 35 |
/* Sidebar */
|
| 36 |
+
--sidebar-width: 240px;
|
| 37 |
+
--sidebar-collapsed-width: 70px;
|
| 38 |
|
| 39 |
/* Gradients */
|
| 40 |
--gradient-purple: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
|
|
|
| 114 |
}
|
| 115 |
|
| 116 |
.sidebar-header {
|
| 117 |
+
padding: 16px 16px;
|
| 118 |
border-bottom: 1px solid var(--border);
|
| 119 |
display: flex;
|
| 120 |
justify-content: space-between;
|
|
|
|
| 124 |
.sidebar-logo {
|
| 125 |
display: flex;
|
| 126 |
align-items: center;
|
| 127 |
+
gap: 10px;
|
| 128 |
transition: var(--transition-normal);
|
| 129 |
}
|
| 130 |
|
|
|
|
| 134 |
}
|
| 135 |
|
| 136 |
.sidebar-logo .logo-icon {
|
| 137 |
+
width: 36px;
|
| 138 |
+
height: 36px;
|
| 139 |
background: var(--gradient-purple);
|
| 140 |
+
border-radius: 10px;
|
| 141 |
display: flex;
|
| 142 |
align-items: center;
|
| 143 |
justify-content: center;
|
|
|
|
| 153 |
}
|
| 154 |
|
| 155 |
.sidebar-logo .logo-text h1 {
|
| 156 |
+
font-size: 17px;
|
| 157 |
font-weight: 800;
|
| 158 |
background: linear-gradient(135deg, var(--primary), var(--secondary));
|
| 159 |
-webkit-background-clip: text;
|
|
|
|
| 163 |
}
|
| 164 |
|
| 165 |
.sidebar-logo .logo-text p {
|
| 166 |
+
font-size: 10px;
|
| 167 |
color: var(--text-secondary);
|
| 168 |
font-weight: 500;
|
| 169 |
}
|
|
|
|
| 188 |
/* Sidebar Navigation */
|
| 189 |
.sidebar-nav {
|
| 190 |
flex: 1;
|
| 191 |
+
padding: 14px 12px;
|
| 192 |
overflow-y: auto;
|
| 193 |
}
|
| 194 |
|
| 195 |
.nav-item {
|
| 196 |
display: flex;
|
| 197 |
align-items: center;
|
| 198 |
+
gap: 10px;
|
| 199 |
+
padding: 11px 14px;
|
| 200 |
background: transparent;
|
| 201 |
border: 1px solid transparent;
|
| 202 |
+
border-radius: 10px;
|
| 203 |
color: var(--text-secondary);
|
| 204 |
cursor: pointer;
|
| 205 |
+
font-size: 14px;
|
| 206 |
font-weight: 600;
|
| 207 |
transition: all var(--transition-fast);
|
| 208 |
width: 100%;
|
| 209 |
text-align: left;
|
| 210 |
+
margin-bottom: 6px;
|
| 211 |
}
|
| 212 |
|
| 213 |
.nav-item svg {
|
| 214 |
+
width: 18px;
|
| 215 |
+
height: 18px;
|
| 216 |
flex-shrink: 0;
|
| 217 |
stroke-width: 2;
|
| 218 |
}
|
|
|
|
| 233 |
|
| 234 |
/* Sidebar Footer */
|
| 235 |
.sidebar-footer {
|
| 236 |
+
padding: 14px 16px;
|
| 237 |
border-top: 1px solid var(--border);
|
| 238 |
}
|
| 239 |
|
static/js/app.js
CHANGED
|
@@ -6,6 +6,8 @@
|
|
| 6 |
// =============================================================================
|
| 7 |
(function() {
|
| 8 |
const originalWarn = console.warn;
|
|
|
|
|
|
|
| 9 |
console.warn = function(...args) {
|
| 10 |
const message = args.join(' ');
|
| 11 |
// Suppress Permissions-Policy warnings from external servers (e.g., Hugging Face)
|
|
@@ -22,6 +24,18 @@
|
|
| 22 |
}
|
| 23 |
originalWarn.apply(console, args);
|
| 24 |
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 25 |
})();
|
| 26 |
|
| 27 |
// =============================================================================
|
|
@@ -856,13 +870,19 @@ async function loadModels() {
|
|
| 856 |
const transformersAvailable = statusData.transformers_available !== undefined ? statusData.transformers_available : false;
|
| 857 |
const statusMessage = statusData.status_message || (isOk ? 'Active' : 'Partial');
|
| 858 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 859 |
modelsStatusDiv.innerHTML = `
|
| 860 |
-
<div class="alert ${
|
| 861 |
-
<strong>Status:</strong> ${
|
| 862 |
-
<strong>
|
| 863 |
-
<strong>
|
| 864 |
<strong>HF Mode:</strong> ${hfMode}<br>
|
| 865 |
-
<strong>Transformers
|
|
|
|
| 866 |
</div>
|
| 867 |
`;
|
| 868 |
|
|
@@ -917,8 +937,9 @@ async function loadModels() {
|
|
| 917 |
const task = model.task || 'N/A';
|
| 918 |
const category = model.category || 'N/A';
|
| 919 |
const isLoaded = model.loaded === true;
|
| 920 |
-
const
|
| 921 |
-
const
|
|
|
|
| 922 |
return `
|
| 923 |
<tr>
|
| 924 |
<td><strong>${modelId}</strong></td>
|
|
|
|
| 6 |
// =============================================================================
|
| 7 |
(function() {
|
| 8 |
const originalWarn = console.warn;
|
| 9 |
+
const originalError = console.error;
|
| 10 |
+
|
| 11 |
console.warn = function(...args) {
|
| 12 |
const message = args.join(' ');
|
| 13 |
// Suppress Permissions-Policy warnings from external servers (e.g., Hugging Face)
|
|
|
|
| 24 |
}
|
| 25 |
originalWarn.apply(console, args);
|
| 26 |
};
|
| 27 |
+
|
| 28 |
+
console.error = function(...args) {
|
| 29 |
+
const message = args.join(' ');
|
| 30 |
+
// Suppress Hugging Face Spaces SSE errors (only relevant for HF deployment)
|
| 31 |
+
if (message.includes('/api/spaces/') && message.includes('/events') ||
|
| 32 |
+
message.includes('Failed to fetch Space status') ||
|
| 33 |
+
message.includes('SSE Stream ended') ||
|
| 34 |
+
message.includes('ERR_HTTP2_PROTOCOL_ERROR')) {
|
| 35 |
+
return; // Suppress these errors (not relevant for local deployment)
|
| 36 |
+
}
|
| 37 |
+
originalError.apply(console, args);
|
| 38 |
+
};
|
| 39 |
})();
|
| 40 |
|
| 41 |
// =============================================================================
|
|
|
|
| 870 |
const transformersAvailable = statusData.transformers_available !== undefined ? statusData.transformers_available : false;
|
| 871 |
const statusMessage = statusData.status_message || (isOk ? 'Active' : 'Partial');
|
| 872 |
|
| 873 |
+
// Determine if lazy loading is active
|
| 874 |
+
const isLazyLoading = hfMode === 'public' && pipelinesLoaded === 0 && modelsCount > 0;
|
| 875 |
+
const alertClass = isLazyLoading ? 'alert-info' : (isOk ? 'alert-success' : 'alert-warning');
|
| 876 |
+
const statusIcon = isLazyLoading ? 'ℹ️' : (isOk ? '✅' : '⚠️');
|
| 877 |
+
|
| 878 |
modelsStatusDiv.innerHTML = `
|
| 879 |
+
<div class="alert ${alertClass}">
|
| 880 |
+
<strong>Status:</strong> ${statusIcon} ${statusMessage}<br>
|
| 881 |
+
<strong>Models Configured:</strong> ${modelsCount} (Lazy Loading)<br>
|
| 882 |
+
<strong>Models Loaded:</strong> ${pipelinesLoaded}<br>
|
| 883 |
<strong>HF Mode:</strong> ${hfMode}<br>
|
| 884 |
+
<strong>Transformers:</strong> ${transformersAvailable ? '✅ Available' : '❌ Not Available'}
|
| 885 |
+
${isLazyLoading ? '<br><br><em>💡 Models will load automatically on first use (sentiment analysis, etc.)</em>' : ''}
|
| 886 |
</div>
|
| 887 |
`;
|
| 888 |
|
|
|
|
| 937 |
const task = model.task || 'N/A';
|
| 938 |
const category = model.category || 'N/A';
|
| 939 |
const isLoaded = model.loaded === true;
|
| 940 |
+
const hasError = model.error && model.error.length > 0;
|
| 941 |
+
const statusClass = isLoaded ? 'available' : (hasError ? 'error' : 'standby');
|
| 942 |
+
const statusText = isLoaded ? '✅ Loaded' : (hasError ? '❌ Error' : '⏸️ Standby');
|
| 943 |
return `
|
| 944 |
<tr>
|
| 945 |
<td><strong>${modelId}</strong></td>
|