theguywhosucks commited on
Commit
821b0e4
·
verified ·
1 Parent(s): f3561c0

Upload 15 files

Browse files
Files changed (4) hide show
  1. dashboardlogic.js +31 -99
  2. logic.js +15 -11
  3. package.json +1 -1
  4. 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 client.predict("/search_user", withTokens({ user_id: currentUser }));
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 client.predict("/get_files_secure", withTokens({
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 // for preview content
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 client.predict("/delete_file_secure", withTokens({
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 /get_download_link_action to get the raw download link
416
- const result = await client.predict("/get_download_link_action", withTokens({
417
- user_id: currentUser,
418
- password: currentPassword,
419
- filename: file.name,
420
- }));
421
- const fileUrl = result.data[0];
422
- if (typeof fileUrl === 'string' && (fileUrl.startsWith('http') || fileUrl.startsWith('https'))) {
423
- // Fetch as blob to force download, with optional Hugging Face token
424
- const hfToken = sessionStorage.getItem('hf_read_token');
425
- const fetchOptions = hfToken ? {
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
- try {
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 client = await Client.connect("pockit-cloud/main");
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 client = await Client.connect("pockit-cloud/main");
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.0.0",
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
- const express = require("express");
2
- const path = require("path");
 
 
 
 
 
 
3
 
4
  const app = express();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5
 
6
- app.use(express.static(__dirname));
 
7
 
8
- app.listen(7860, () => {
9
- console.log("Server running on port 7860");
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
+ });