Spaces:
Sleeping
Sleeping
Upload 15 files
Browse files- dashboardlogic.js +31 -99
- logic.js +15 -11
- package.json +1 -1
- server.js +60 -6
dashboardlogic.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
| 1 |
|
| 2 |
-
import { Client } from "https://cdn.jsdelivr.net/npm/@gradio/client@1.9.0/dist/index.min.js";
|
| 3 |
|
| 4 |
// Read/write tokens from sessionStorage
|
| 5 |
function getReadToken() {
|
|
@@ -9,7 +9,7 @@ function getWriteToken() {
|
|
| 9 |
return sessionStorage.getItem('hf_write_token') || '';
|
| 10 |
}
|
| 11 |
|
| 12 |
-
// Helper to add tokens to every API call
|
| 13 |
function withTokens(obj = {}) {
|
| 14 |
return {
|
| 15 |
...obj,
|
|
@@ -18,6 +18,17 @@ function withTokens(obj = {}) {
|
|
| 18 |
};
|
| 19 |
}
|
| 20 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 21 |
let client;
|
| 22 |
let currentUser = null;
|
| 23 |
let currentPassword = null;
|
|
@@ -53,18 +64,13 @@ async function initDashboard() {
|
|
| 53 |
}
|
| 54 |
|
| 55 |
try {
|
| 56 |
-
client = await Client.connect("pockit-cloud/main");
|
| 57 |
-
console.log('✓ Connected to API');
|
| 58 |
-
|
| 59 |
// Update account info
|
| 60 |
const initials = currentUser.substring(0, 2).toUpperCase();
|
| 61 |
document.querySelector('.avatar').textContent = initials;
|
| 62 |
document.querySelector('.account-name').textContent = currentUser;
|
| 63 |
-
|
| 64 |
// Load data
|
| 65 |
await loadUserData();
|
| 66 |
await loadFiles();
|
| 67 |
-
|
| 68 |
} catch (err) {
|
| 69 |
console.error('Init error:', err);
|
| 70 |
showToast('Connection failed');
|
|
@@ -76,38 +82,29 @@ async function initDashboard() {
|
|
| 76 |
async function loadUserData() {
|
| 77 |
try {
|
| 78 |
console.log('Loading user data...');
|
| 79 |
-
const result = await
|
| 80 |
const [log, isDev, isPro, isTester, capacityUsed, usedTotal] = result.data;
|
| 81 |
-
|
| 82 |
-
// Determine role
|
| 83 |
let role = 'free';
|
| 84 |
if (isDev) role = 'dev';
|
| 85 |
else if (isPro) role = 'pro';
|
| 86 |
else if (isTester) role = 'tester';
|
| 87 |
-
|
| 88 |
const tag = document.getElementById('role-tag');
|
| 89 |
tag.className = 'role-tag ' + role;
|
| 90 |
tag.textContent = role.charAt(0).toUpperCase() + role.slice(1);
|
| 91 |
document.getElementById('tier-val').textContent = tag.textContent;
|
| 92 |
-
|
| 93 |
-
// Parse capacity
|
| 94 |
const capacityPercent = Math.round(capacityUsed);
|
| 95 |
let usedDisplay = usedTotal || '0 / 5 GB';
|
| 96 |
let usedParts = usedDisplay.split('/');
|
| 97 |
let usedAmount = usedParts[0].trim();
|
| 98 |
let maxAmount = usedParts[1] ? usedParts[1].trim() : '5 GB';
|
| 99 |
-
|
| 100 |
-
// Update storage displays
|
| 101 |
document.querySelector('.card-bar-fill').style.width = capacityPercent + '%';
|
| 102 |
document.querySelector('.stor-label span:last-child').textContent = usedDisplay;
|
| 103 |
document.querySelector('.sbar-fill').style.width = capacityPercent + '%';
|
| 104 |
-
|
| 105 |
const storageCard = document.querySelectorAll('.card')[0];
|
| 106 |
-
storageCard.querySelector('.card-val').innerHTML = usedAmount + ' <span style="font-size:.38em;font-weight:400;color:rgba(0,0,0,.38)">(' + capacityPercent + '%)</span>';
|
| 107 |
storageCard.querySelector('.card-sub').textContent = usedDisplay + ' used';
|
| 108 |
-
|
| 109 |
document.querySelectorAll('.card')[3].querySelector('.card-sub').textContent = maxAmount + ' max capacity';
|
| 110 |
-
|
| 111 |
console.log('✓ User data loaded');
|
| 112 |
} catch (err) {
|
| 113 |
console.error('User data error:', err);
|
|
@@ -123,26 +120,21 @@ async function loadFiles() {
|
|
| 123 |
try {
|
| 124 |
console.log('Loading files...');
|
| 125 |
loading(true);
|
| 126 |
-
const result = await
|
| 127 |
user_id: currentUser,
|
| 128 |
password: currentPassword,
|
| 129 |
}));
|
| 130 |
// API returns [dropdown, status]
|
| 131 |
const dropdownData = result.data[0];
|
| 132 |
-
console.log('Raw dropdownData:', dropdownData);
|
| 133 |
let fileNames = [];
|
| 134 |
if (dropdownData && typeof dropdownData === 'object' && dropdownData.choices) {
|
| 135 |
-
// Flatten all sub-arrays in choices
|
| 136 |
fileNames = dropdownData.choices.flat ? dropdownData.choices.flat() : [].concat(...dropdownData.choices);
|
| 137 |
} else if (Array.isArray(dropdownData)) {
|
| 138 |
fileNames = dropdownData;
|
| 139 |
} else if (typeof dropdownData === 'string') {
|
| 140 |
fileNames = [dropdownData];
|
| 141 |
}
|
| 142 |
-
// Convert all to string, trim, and filter empty
|
| 143 |
fileNames = fileNames.map(f => String(f).trim()).filter(Boolean);
|
| 144 |
-
console.log('Extracted fileNames from dropdown:', fileNames);
|
| 145 |
-
// Deduplicate file names (case-insensitive, trim)
|
| 146 |
const seen = new Set();
|
| 147 |
const deduped = [];
|
| 148 |
for (const name of fileNames) {
|
|
@@ -160,15 +152,13 @@ async function loadFiles() {
|
|
| 160 |
size: '—',
|
| 161 |
date: 'Recently',
|
| 162 |
type: ext ? ext.toUpperCase() : '',
|
| 163 |
-
preview: null
|
| 164 |
};
|
| 165 |
});
|
| 166 |
-
console.log('Final files array before render:', files);
|
| 167 |
selected.clear();
|
| 168 |
updateStatsCards();
|
| 169 |
render(files);
|
| 170 |
loading(false);
|
| 171 |
-
console.log('✓ Files loaded and rendered');
|
| 172 |
} catch (err) {
|
| 173 |
console.error('Files load error:', err);
|
| 174 |
loading(false);
|
|
@@ -354,25 +344,18 @@ async function deleteFile(id) {
|
|
| 354 |
|
| 355 |
try {
|
| 356 |
loading(true);
|
| 357 |
-
const result = await
|
| 358 |
user_id: currentUser,
|
| 359 |
password: currentPassword,
|
| 360 |
filename: file.name,
|
| 361 |
}));
|
| 362 |
-
|
| 363 |
-
console.log('Deleted:', file.name);
|
| 364 |
-
|
| 365 |
-
// Update storage
|
| 366 |
const [status, capacityUsed, usedTotal] = result.data;
|
| 367 |
const percent = Math.round(capacityUsed);
|
| 368 |
document.querySelector('.card-bar-fill').style.width = percent + '%';
|
| 369 |
document.querySelector('.sbar-fill').style.width = percent + '%';
|
| 370 |
document.querySelector('.stor-label span:last-child').textContent = usedTotal;
|
| 371 |
-
|
| 372 |
-
// Remove from array
|
| 373 |
files.splice(id, 1);
|
| 374 |
selected.delete(id);
|
| 375 |
-
|
| 376 |
updateStatsCards();
|
| 377 |
render(files);
|
| 378 |
loading(false);
|
|
@@ -412,43 +395,17 @@ async function downloadFile(id) {
|
|
| 412 |
const file = files[id];
|
| 413 |
try {
|
| 414 |
loading(true);
|
| 415 |
-
// Use /
|
| 416 |
-
const
|
| 417 |
-
|
| 418 |
-
|
| 419 |
-
|
| 420 |
-
|
| 421 |
-
|
| 422 |
-
|
| 423 |
-
|
| 424 |
-
|
| 425 |
-
|
| 426 |
-
headers: { 'Authorization': 'Bearer ' + hfToken }
|
| 427 |
-
} : {};
|
| 428 |
-
const response = await fetch(fileUrl, fetchOptions);
|
| 429 |
-
if (!response.ok) {
|
| 430 |
-
console.error('Download fetch error:', {
|
| 431 |
-
url: fileUrl,
|
| 432 |
-
status: response.status,
|
| 433 |
-
statusText: response.statusText
|
| 434 |
-
});
|
| 435 |
-
throw new Error('Network response was not ok (status ' + response.status + '): ' + response.statusText);
|
| 436 |
-
}
|
| 437 |
-
const blob = await response.blob();
|
| 438 |
-
const url = window.URL.createObjectURL(blob);
|
| 439 |
-
const a = document.createElement('a');
|
| 440 |
-
a.href = url;
|
| 441 |
-
a.download = file.name;
|
| 442 |
-
document.body.appendChild(a);
|
| 443 |
-
a.click();
|
| 444 |
-
setTimeout(() => {
|
| 445 |
-
document.body.removeChild(a);
|
| 446 |
-
window.URL.revokeObjectURL(url);
|
| 447 |
-
}, 100);
|
| 448 |
-
showToast('Download started: ' + file.name);
|
| 449 |
-
} else {
|
| 450 |
-
showToast('Download link error');
|
| 451 |
-
}
|
| 452 |
loading(false);
|
| 453 |
} catch (err) {
|
| 454 |
console.error('Download error:', err);
|
|
@@ -469,32 +426,7 @@ async function downloadPreviewFile() {
|
|
| 469 |
async function handleUpload(input) {
|
| 470 |
if (!input.files || !input.files[0]) return;
|
| 471 |
const file = input.files[0];
|
| 472 |
-
|
| 473 |
-
loading(true);
|
| 474 |
-
// Use File object and pass custom_name for filename preservation
|
| 475 |
-
console.log('Uploading file:', file, 'type:', file.constructor.name);
|
| 476 |
-
const result = await client.predict("/upload_file_secure", withTokens({
|
| 477 |
-
user_id: currentUser,
|
| 478 |
-
password: currentPassword,
|
| 479 |
-
filepath: file,
|
| 480 |
-
custom_name: file.name,
|
| 481 |
-
}));
|
| 482 |
-
console.log('Uploaded:', file.name);
|
| 483 |
-
// Update storage
|
| 484 |
-
const [status, capacityUsed, usedTotal] = result.data;
|
| 485 |
-
const percent = Math.round(capacityUsed);
|
| 486 |
-
document.querySelector('.card-bar-fill').style.width = percent + '%';
|
| 487 |
-
document.querySelector('.sbar-fill').style.width = percent + '%';
|
| 488 |
-
document.querySelector('.stor-label span:last-child').textContent = usedTotal;
|
| 489 |
-
// Reload files
|
| 490 |
-
await loadFiles();
|
| 491 |
-
showToast(file.name + ' uploaded');
|
| 492 |
-
input.value = '';
|
| 493 |
-
} catch (err) {
|
| 494 |
-
console.error('Upload error:', err);
|
| 495 |
-
loading(false);
|
| 496 |
-
showToast('Upload failed');
|
| 497 |
-
}
|
| 498 |
}
|
| 499 |
|
| 500 |
function handleDrop(e) {
|
|
|
|
| 1 |
|
| 2 |
+
// import { Client } from "https://cdn.jsdelivr.net/npm/@gradio/client@1.9.0/dist/index.min.js";
|
| 3 |
|
| 4 |
// Read/write tokens from sessionStorage
|
| 5 |
function getReadToken() {
|
|
|
|
| 9 |
return sessionStorage.getItem('hf_write_token') || '';
|
| 10 |
}
|
| 11 |
|
| 12 |
+
// Helper to add tokens to every API call (kept for compatibility, but not used for server tokens)
|
| 13 |
function withTokens(obj = {}) {
|
| 14 |
return {
|
| 15 |
...obj,
|
|
|
|
| 18 |
};
|
| 19 |
}
|
| 20 |
|
| 21 |
+
// Helper to call secure server-side proxy
|
| 22 |
+
async function callSecureApi(fn, args) {
|
| 23 |
+
const resp = await fetch('/api/proxy', {
|
| 24 |
+
method: 'POST',
|
| 25 |
+
headers: { 'Content-Type': 'application/json' },
|
| 26 |
+
body: JSON.stringify({ fn, args })
|
| 27 |
+
});
|
| 28 |
+
if (!resp.ok) throw new Error('Proxy error: ' + resp.status);
|
| 29 |
+
return await resp.json();
|
| 30 |
+
}
|
| 31 |
+
|
| 32 |
let client;
|
| 33 |
let currentUser = null;
|
| 34 |
let currentPassword = null;
|
|
|
|
| 64 |
}
|
| 65 |
|
| 66 |
try {
|
|
|
|
|
|
|
|
|
|
| 67 |
// Update account info
|
| 68 |
const initials = currentUser.substring(0, 2).toUpperCase();
|
| 69 |
document.querySelector('.avatar').textContent = initials;
|
| 70 |
document.querySelector('.account-name').textContent = currentUser;
|
|
|
|
| 71 |
// Load data
|
| 72 |
await loadUserData();
|
| 73 |
await loadFiles();
|
|
|
|
| 74 |
} catch (err) {
|
| 75 |
console.error('Init error:', err);
|
| 76 |
showToast('Connection failed');
|
|
|
|
| 82 |
async function loadUserData() {
|
| 83 |
try {
|
| 84 |
console.log('Loading user data...');
|
| 85 |
+
const result = await callSecureApi("/search_user", withTokens({ user_id: currentUser }));
|
| 86 |
const [log, isDev, isPro, isTester, capacityUsed, usedTotal] = result.data;
|
| 87 |
+
// ...existing code...
|
|
|
|
| 88 |
let role = 'free';
|
| 89 |
if (isDev) role = 'dev';
|
| 90 |
else if (isPro) role = 'pro';
|
| 91 |
else if (isTester) role = 'tester';
|
|
|
|
| 92 |
const tag = document.getElementById('role-tag');
|
| 93 |
tag.className = 'role-tag ' + role;
|
| 94 |
tag.textContent = role.charAt(0).toUpperCase() + role.slice(1);
|
| 95 |
document.getElementById('tier-val').textContent = tag.textContent;
|
|
|
|
|
|
|
| 96 |
const capacityPercent = Math.round(capacityUsed);
|
| 97 |
let usedDisplay = usedTotal || '0 / 5 GB';
|
| 98 |
let usedParts = usedDisplay.split('/');
|
| 99 |
let usedAmount = usedParts[0].trim();
|
| 100 |
let maxAmount = usedParts[1] ? usedParts[1].trim() : '5 GB';
|
|
|
|
|
|
|
| 101 |
document.querySelector('.card-bar-fill').style.width = capacityPercent + '%';
|
| 102 |
document.querySelector('.stor-label span:last-child').textContent = usedDisplay;
|
| 103 |
document.querySelector('.sbar-fill').style.width = capacityPercent + '%';
|
|
|
|
| 104 |
const storageCard = document.querySelectorAll('.card')[0];
|
| 105 |
+
storageCard.querySelector('.card-val').innerHTML = usedAmount + ' <span style="font-size:.38em;font-weight:400;color:rgba(0,0,0,.38)">( ' + capacityPercent + '%)</span>';
|
| 106 |
storageCard.querySelector('.card-sub').textContent = usedDisplay + ' used';
|
|
|
|
| 107 |
document.querySelectorAll('.card')[3].querySelector('.card-sub').textContent = maxAmount + ' max capacity';
|
|
|
|
| 108 |
console.log('✓ User data loaded');
|
| 109 |
} catch (err) {
|
| 110 |
console.error('User data error:', err);
|
|
|
|
| 120 |
try {
|
| 121 |
console.log('Loading files...');
|
| 122 |
loading(true);
|
| 123 |
+
const result = await callSecureApi("/get_files_secure", withTokens({
|
| 124 |
user_id: currentUser,
|
| 125 |
password: currentPassword,
|
| 126 |
}));
|
| 127 |
// API returns [dropdown, status]
|
| 128 |
const dropdownData = result.data[0];
|
|
|
|
| 129 |
let fileNames = [];
|
| 130 |
if (dropdownData && typeof dropdownData === 'object' && dropdownData.choices) {
|
|
|
|
| 131 |
fileNames = dropdownData.choices.flat ? dropdownData.choices.flat() : [].concat(...dropdownData.choices);
|
| 132 |
} else if (Array.isArray(dropdownData)) {
|
| 133 |
fileNames = dropdownData;
|
| 134 |
} else if (typeof dropdownData === 'string') {
|
| 135 |
fileNames = [dropdownData];
|
| 136 |
}
|
|
|
|
| 137 |
fileNames = fileNames.map(f => String(f).trim()).filter(Boolean);
|
|
|
|
|
|
|
| 138 |
const seen = new Set();
|
| 139 |
const deduped = [];
|
| 140 |
for (const name of fileNames) {
|
|
|
|
| 152 |
size: '—',
|
| 153 |
date: 'Recently',
|
| 154 |
type: ext ? ext.toUpperCase() : '',
|
| 155 |
+
preview: null
|
| 156 |
};
|
| 157 |
});
|
|
|
|
| 158 |
selected.clear();
|
| 159 |
updateStatsCards();
|
| 160 |
render(files);
|
| 161 |
loading(false);
|
|
|
|
| 162 |
} catch (err) {
|
| 163 |
console.error('Files load error:', err);
|
| 164 |
loading(false);
|
|
|
|
| 344 |
|
| 345 |
try {
|
| 346 |
loading(true);
|
| 347 |
+
const result = await callSecureApi("/delete_file_secure", withTokens({
|
| 348 |
user_id: currentUser,
|
| 349 |
password: currentPassword,
|
| 350 |
filename: file.name,
|
| 351 |
}));
|
|
|
|
|
|
|
|
|
|
|
|
|
| 352 |
const [status, capacityUsed, usedTotal] = result.data;
|
| 353 |
const percent = Math.round(capacityUsed);
|
| 354 |
document.querySelector('.card-bar-fill').style.width = percent + '%';
|
| 355 |
document.querySelector('.sbar-fill').style.width = percent + '%';
|
| 356 |
document.querySelector('.stor-label span:last-child').textContent = usedTotal;
|
|
|
|
|
|
|
| 357 |
files.splice(id, 1);
|
| 358 |
selected.delete(id);
|
|
|
|
| 359 |
updateStatsCards();
|
| 360 |
render(files);
|
| 361 |
loading(false);
|
|
|
|
| 395 |
const file = files[id];
|
| 396 |
try {
|
| 397 |
loading(true);
|
| 398 |
+
// Use /api/download endpoint to stream file securely
|
| 399 |
+
const url = `/api/download?file=${encodeURIComponent(file.name)}`;
|
| 400 |
+
const a = document.createElement('a');
|
| 401 |
+
a.href = url;
|
| 402 |
+
a.download = file.name;
|
| 403 |
+
document.body.appendChild(a);
|
| 404 |
+
a.click();
|
| 405 |
+
setTimeout(() => {
|
| 406 |
+
document.body.removeChild(a);
|
| 407 |
+
}, 100);
|
| 408 |
+
showToast('Download started: ' + file.name);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 409 |
loading(false);
|
| 410 |
} catch (err) {
|
| 411 |
console.error('Download error:', err);
|
|
|
|
| 426 |
async function handleUpload(input) {
|
| 427 |
if (!input.files || !input.files[0]) return;
|
| 428 |
const file = input.files[0];
|
| 429 |
+
alert('Upload via proxy not yet implemented.');
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 430 |
}
|
| 431 |
|
| 432 |
function handleDrop(e) {
|
logic.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
| 1 |
|
| 2 |
-
import { Client } from "https://cdn.jsdelivr.net/npm/@gradio/client@1.9.0/dist/index.min.js";
|
| 3 |
|
| 4 |
// Read/write tokens from sessionStorage
|
| 5 |
function getReadToken() {
|
|
@@ -18,6 +18,17 @@ function withTokens(obj = {}) {
|
|
| 18 |
};
|
| 19 |
}
|
| 20 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 21 |
const loginForm = document.getElementById('loginForm');
|
| 22 |
const signupForm = document.getElementById('signupForm');
|
| 23 |
|
|
@@ -62,15 +73,12 @@ if (signupForm) {
|
|
| 62 |
const pass = document.getElementById('password').value;
|
| 63 |
|
| 64 |
try {
|
| 65 |
-
const
|
| 66 |
-
const result = await client.predict("/create_user", withTokens({
|
| 67 |
user_id: user,
|
| 68 |
password: pass,
|
| 69 |
}));
|
| 70 |
-
|
| 71 |
// Debug: log the result
|
| 72 |
console.log("/create_user result:", result.data);
|
| 73 |
-
|
| 74 |
let log = "";
|
| 75 |
if (typeof result.data === "string") {
|
| 76 |
log = result.data.toLowerCase();
|
|
@@ -79,7 +87,6 @@ if (signupForm) {
|
|
| 79 |
} else if (typeof result.data === "object" && result.data !== null) {
|
| 80 |
log = JSON.stringify(result.data).toLowerCase();
|
| 81 |
}
|
| 82 |
-
|
| 83 |
if (log.includes("success") || log.includes("user created")) {
|
| 84 |
sessionStorage.setItem("pockit_user", user);
|
| 85 |
sessionStorage.setItem("pockit_pass", pass);
|
|
@@ -105,15 +112,12 @@ if (loginForm) {
|
|
| 105 |
const pass = document.getElementById('password').value;
|
| 106 |
|
| 107 |
try {
|
| 108 |
-
const
|
| 109 |
-
const result = await client.predict("/get_files_secure", withTokens({
|
| 110 |
user_id: user,
|
| 111 |
password: pass,
|
| 112 |
}));
|
| 113 |
-
|
| 114 |
// Status message is at index 1 for get_files_secure
|
| 115 |
-
const status = result.data[1].toLowerCase();
|
| 116 |
-
|
| 117 |
if (status.includes("found") || status.includes("success")) {
|
| 118 |
sessionStorage.setItem("pockit_user", user);
|
| 119 |
sessionStorage.setItem("pockit_pass", pass);
|
|
|
|
| 1 |
|
| 2 |
+
// import { Client } from "https://cdn.jsdelivr.net/npm/@gradio/client@1.9.0/dist/index.min.js";
|
| 3 |
|
| 4 |
// Read/write tokens from sessionStorage
|
| 5 |
function getReadToken() {
|
|
|
|
| 18 |
};
|
| 19 |
}
|
| 20 |
|
| 21 |
+
// Helper to call secure server-side proxy
|
| 22 |
+
async function callSecureApi(fn, args) {
|
| 23 |
+
const resp = await fetch('/api/proxy', {
|
| 24 |
+
method: 'POST',
|
| 25 |
+
headers: { 'Content-Type': 'application/json' },
|
| 26 |
+
body: JSON.stringify({ fn, args })
|
| 27 |
+
});
|
| 28 |
+
if (!resp.ok) throw new Error('Proxy error: ' + resp.status);
|
| 29 |
+
return await resp.json();
|
| 30 |
+
}
|
| 31 |
+
|
| 32 |
const loginForm = document.getElementById('loginForm');
|
| 33 |
const signupForm = document.getElementById('signupForm');
|
| 34 |
|
|
|
|
| 73 |
const pass = document.getElementById('password').value;
|
| 74 |
|
| 75 |
try {
|
| 76 |
+
const result = await callSecureApi("/create_user", withTokens({
|
|
|
|
| 77 |
user_id: user,
|
| 78 |
password: pass,
|
| 79 |
}));
|
|
|
|
| 80 |
// Debug: log the result
|
| 81 |
console.log("/create_user result:", result.data);
|
|
|
|
| 82 |
let log = "";
|
| 83 |
if (typeof result.data === "string") {
|
| 84 |
log = result.data.toLowerCase();
|
|
|
|
| 87 |
} else if (typeof result.data === "object" && result.data !== null) {
|
| 88 |
log = JSON.stringify(result.data).toLowerCase();
|
| 89 |
}
|
|
|
|
| 90 |
if (log.includes("success") || log.includes("user created")) {
|
| 91 |
sessionStorage.setItem("pockit_user", user);
|
| 92 |
sessionStorage.setItem("pockit_pass", pass);
|
|
|
|
| 112 |
const pass = document.getElementById('password').value;
|
| 113 |
|
| 114 |
try {
|
| 115 |
+
const result = await callSecureApi("/get_files_secure", withTokens({
|
|
|
|
| 116 |
user_id: user,
|
| 117 |
password: pass,
|
| 118 |
}));
|
|
|
|
| 119 |
// Status message is at index 1 for get_files_secure
|
| 120 |
+
const status = result.data[1]?.toLowerCase?.() || "";
|
|
|
|
| 121 |
if (status.includes("found") || status.includes("success")) {
|
| 122 |
sessionStorage.setItem("pockit_user", user);
|
| 123 |
sessionStorage.setItem("pockit_pass", pass);
|
package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
| 2 |
"name": "hf-web",
|
| 3 |
"version": "1.0.0",
|
| 4 |
"dependencies": {
|
| 5 |
-
"@gradio/client": "^1.
|
| 6 |
"express": "^4.18.2"
|
| 7 |
}
|
| 8 |
}
|
|
|
|
| 2 |
"name": "hf-web",
|
| 3 |
"version": "1.0.0",
|
| 4 |
"dependencies": {
|
| 5 |
+
"@gradio/client": "^1.9.0",
|
| 6 |
"express": "^4.18.2"
|
| 7 |
}
|
| 8 |
}
|
server.js
CHANGED
|
@@ -1,10 +1,64 @@
|
|
| 1 |
-
|
| 2 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 3 |
|
| 4 |
const app = express();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 5 |
|
| 6 |
-
|
|
|
|
| 7 |
|
| 8 |
-
app.listen(
|
| 9 |
-
console.log(
|
| 10 |
-
});
|
|
|
|
| 1 |
+
// server.js
|
| 2 |
+
import express from "express";
|
| 3 |
+
import { Client } from "@gradio/client";
|
| 4 |
+
import dotenv from "dotenv";
|
| 5 |
+
import fetch from "node-fetch";
|
| 6 |
+
|
| 7 |
+
// Load environment variables (HF_TOKEN)
|
| 8 |
+
dotenv.config();
|
| 9 |
|
| 10 |
const app = express();
|
| 11 |
+
const PORT = process.env.PORT || 7860;
|
| 12 |
+
const HF_TOKEN = process.env.HF_TOKEN;
|
| 13 |
+
|
| 14 |
+
if (!HF_TOKEN) {
|
| 15 |
+
console.error("HF_TOKEN is not set in environment variables!");
|
| 16 |
+
process.exit(1);
|
| 17 |
+
}
|
| 18 |
+
|
| 19 |
+
app.use(express.json({ limit: "10mb" }));
|
| 20 |
+
|
| 21 |
+
// Secure proxy endpoint for Gradio API
|
| 22 |
+
app.post("/api/proxy", async (req, res) => {
|
| 23 |
+
const { fn, args } = req.body;
|
| 24 |
+
if (!fn) return res.status(400).json({ error: "Missing 'fn' in request body" });
|
| 25 |
+
|
| 26 |
+
try {
|
| 27 |
+
const client = await Client.connect("pockit-cloud/main", { hf_token: HF_TOKEN });
|
| 28 |
+
const result = await client.predict(fn, args);
|
| 29 |
+
res.json({ data: result.data });
|
| 30 |
+
} catch (err) {
|
| 31 |
+
console.error("Proxy error:", err);
|
| 32 |
+
res.status(500).json({ error: "Proxy call failed", details: err.message });
|
| 33 |
+
}
|
| 34 |
+
});
|
| 35 |
+
|
| 36 |
+
// Download endpoint for Hugging Face Datasets
|
| 37 |
+
app.get("/api/download", async (req, res) => {
|
| 38 |
+
const { file } = req.query;
|
| 39 |
+
if (!file) return res.status(400).json({ error: "Missing 'file' query param" });
|
| 40 |
+
|
| 41 |
+
// Example: file = "username/dataset/blob/main/path/to/file.txt"
|
| 42 |
+
const url = `https://huggingface.co/datasets/${file}`;
|
| 43 |
+
try {
|
| 44 |
+
const response = await fetch(url, {
|
| 45 |
+
headers: { Authorization: `Bearer ${HF_TOKEN}` },
|
| 46 |
+
});
|
| 47 |
+
if (!response.ok) {
|
| 48 |
+
return res.status(response.status).json({ error: "File fetch failed" });
|
| 49 |
+
}
|
| 50 |
+
res.setHeader("Content-Disposition", `attachment; filename=\"${file.split("/").pop()}\"`);
|
| 51 |
+
res.setHeader("Content-Type", response.headers.get("content-type") || "application/octet-stream");
|
| 52 |
+
response.body.pipe(res);
|
| 53 |
+
} catch (err) {
|
| 54 |
+
console.error("Download error:", err);
|
| 55 |
+
res.status(500).json({ error: "Download failed", details: err.message });
|
| 56 |
+
}
|
| 57 |
+
});
|
| 58 |
|
| 59 |
+
// Serve static files (frontend)
|
| 60 |
+
app.use(express.static("."));
|
| 61 |
|
| 62 |
+
app.listen(PORT, () => {
|
| 63 |
+
console.log(`Server running on port ${PORT}`);
|
| 64 |
+
});
|