Spaces:
Running
Running
Update index.html
Browse files- index.html +185 -22
index.html
CHANGED
|
@@ -873,7 +873,7 @@
|
|
| 873 |
function showLoginModal() {
|
| 874 |
loginModal.style.display = 'flex';
|
| 875 |
usernameInput.focus();
|
| 876 |
-
|
| 877 |
updateAuthModal();
|
| 878 |
}
|
| 879 |
|
|
@@ -884,7 +884,7 @@
|
|
| 884 |
function toggleAuthMode() {
|
| 885 |
isLoginMode = !isLoginMode;
|
| 886 |
updateAuthModal();
|
| 887 |
-
|
| 888 |
usernameInput.value = '';
|
| 889 |
passwordInput.value = '';
|
| 890 |
usernameInput.focus();
|
|
@@ -947,11 +947,10 @@
|
|
| 947 |
isLoggedIn = true;
|
| 948 |
currentUser.textContent = username;
|
| 949 |
hideLoginModal();
|
| 950 |
-
|
| 951 |
-
|
| 952 |
-
|
| 953 |
-
|
| 954 |
-
addBotMessage('β
Login successful! Please enter your GROQ API key to continue.');
|
| 955 |
} else if (response.status === 401) {
|
| 956 |
showLoginError('Invalid username or password');
|
| 957 |
} else {
|
|
@@ -994,8 +993,148 @@
|
|
| 994 |
}
|
| 995 |
|
| 996 |
function showLoginError(message) {
|
| 997 |
-
|
| 998 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 999 |
}
|
| 1000 |
|
| 1001 |
function logout() {
|
|
@@ -1025,13 +1164,17 @@
|
|
| 1025 |
|
| 1026 |
// β
API Key Functions
|
| 1027 |
function toggleApiKeyVisibility() {
|
| 1028 |
-
|
|
|
|
| 1029 |
const button = document.querySelector('.toggle-visibility');
|
| 1030 |
-
|
| 1031 |
-
|
|
|
|
|
|
|
|
|
|
| 1032 |
button.textContent = 'π';
|
| 1033 |
} else {
|
| 1034 |
-
|
| 1035 |
button.textContent = 'ποΈ';
|
| 1036 |
}
|
| 1037 |
}
|
|
@@ -1042,9 +1185,14 @@
|
|
| 1042 |
return;
|
| 1043 |
}
|
| 1044 |
// Clear the API key input for new users
|
| 1045 |
-
|
|
|
|
|
|
|
|
|
|
| 1046 |
apiKeyModal.style.display = 'flex';
|
| 1047 |
-
|
|
|
|
|
|
|
| 1048 |
}
|
| 1049 |
|
| 1050 |
function hideApiKeyModal() {
|
|
@@ -1052,14 +1200,23 @@
|
|
| 1052 |
}
|
| 1053 |
|
| 1054 |
async function setApiKey() {
|
| 1055 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1056 |
if (!key) {
|
| 1057 |
alert('Please enter a valid API key');
|
| 1058 |
return;
|
| 1059 |
}
|
| 1060 |
|
| 1061 |
-
|
| 1062 |
-
|
| 1063 |
|
| 1064 |
try {
|
| 1065 |
// Send API key to backend for ephemeral storage
|
|
@@ -1083,8 +1240,8 @@
|
|
| 1083 |
console.error('API key setup error:', error);
|
| 1084 |
addBotMessage(`β Failed to connect API key: ${error.message}`);
|
| 1085 |
} finally {
|
| 1086 |
-
|
| 1087 |
-
|
| 1088 |
}
|
| 1089 |
}
|
| 1090 |
|
|
@@ -1303,7 +1460,7 @@
|
|
| 1303 |
return;
|
| 1304 |
}
|
| 1305 |
|
| 1306 |
-
setStatus('processing', 'Loading references...
|
| 1307 |
const formData = new FormData();
|
| 1308 |
formData.append("index", paperIndex.toString());
|
| 1309 |
|
|
@@ -1388,12 +1545,16 @@
|
|
| 1388 |
if (paper.isReference) {
|
| 1389 |
div.style.borderLeft = '4px solid #28a745';
|
| 1390 |
div.style.backgroundColor = 'rgba(40, 167, 69, 0.05)';
|
|
|
|
|
|
|
|
|
|
| 1391 |
}
|
| 1392 |
|
| 1393 |
div.innerHTML = `
|
| 1394 |
<div class="paper-title">
|
| 1395 |
-
${paper.isReference ? 'π ' : ''}${paper.title}
|
| 1396 |
${paper.isReference ? ' <small style="color: #6c757d;">(Reference)</small>' : ''}
|
|
|
|
| 1397 |
</div>
|
| 1398 |
<div class="paper-actions">
|
| 1399 |
${!paper.isReference ? `
|
|
@@ -1459,6 +1620,8 @@
|
|
| 1459 |
window.addReferences = addReferences;
|
| 1460 |
window.logout = logout;
|
| 1461 |
window.toggleAuthMode = toggleAuthMode;
|
|
|
|
|
|
|
| 1462 |
</script>
|
| 1463 |
</body>
|
| 1464 |
</html>
|
|
|
|
| 873 |
function showLoginModal() {
|
| 874 |
loginModal.style.display = 'flex';
|
| 875 |
usernameInput.focus();
|
| 876 |
+
showLoginError(''); // Clear any errors using the error function
|
| 877 |
updateAuthModal();
|
| 878 |
}
|
| 879 |
|
|
|
|
| 884 |
function toggleAuthMode() {
|
| 885 |
isLoginMode = !isLoginMode;
|
| 886 |
updateAuthModal();
|
| 887 |
+
showLoginError(''); // Clear any errors using the error function
|
| 888 |
usernameInput.value = '';
|
| 889 |
passwordInput.value = '';
|
| 890 |
usernameInput.focus();
|
|
|
|
| 947 |
isLoggedIn = true;
|
| 948 |
currentUser.textContent = username;
|
| 949 |
hideLoginModal();
|
| 950 |
+
|
| 951 |
+
// Check for existing user data and API key
|
| 952 |
+
await checkExistingUserData();
|
| 953 |
+
|
|
|
|
| 954 |
} else if (response.status === 401) {
|
| 955 |
showLoginError('Invalid username or password');
|
| 956 |
} else {
|
|
|
|
| 993 |
}
|
| 994 |
|
| 995 |
function showLoginError(message) {
|
| 996 |
+
if (message && message.trim()) {
|
| 997 |
+
loginError.textContent = message;
|
| 998 |
+
loginError.style.display = 'block';
|
| 999 |
+
} else {
|
| 1000 |
+
loginError.textContent = '';
|
| 1001 |
+
loginError.style.display = 'none';
|
| 1002 |
+
}
|
| 1003 |
+
}
|
| 1004 |
+
|
| 1005 |
+
async function checkExistingUserData() {
|
| 1006 |
+
try {
|
| 1007 |
+
// Get user's existing data
|
| 1008 |
+
const userDataResponse = await makeAuthenticatedRequest(`${API_BASE}/user_data/`);
|
| 1009 |
+
if (userDataResponse.ok) {
|
| 1010 |
+
const userData = await userDataResponse.json();
|
| 1011 |
+
|
| 1012 |
+
// Restore papers if user has any
|
| 1013 |
+
if (userData.detailed_papers && userData.detailed_papers.length > 0) {
|
| 1014 |
+
papers = [];
|
| 1015 |
+
let nextId = Date.now();
|
| 1016 |
+
|
| 1017 |
+
userData.detailed_papers.forEach((paperData, index) => {
|
| 1018 |
+
// Add main paper
|
| 1019 |
+
const paper = {
|
| 1020 |
+
id: nextId++,
|
| 1021 |
+
title: paperData.title,
|
| 1022 |
+
type: 'restored',
|
| 1023 |
+
hasReferences: paperData.has_references,
|
| 1024 |
+
referencesLoaded: paperData.references_loaded
|
| 1025 |
+
};
|
| 1026 |
+
papers.push(paper);
|
| 1027 |
+
|
| 1028 |
+
// Add reference papers if they exist
|
| 1029 |
+
if (paperData.references && paperData.references.length > 0) {
|
| 1030 |
+
paperData.references.forEach(refTitle => {
|
| 1031 |
+
papers.push({
|
| 1032 |
+
id: nextId++,
|
| 1033 |
+
title: refTitle,
|
| 1034 |
+
type: 'reference',
|
| 1035 |
+
hasReferences: false,
|
| 1036 |
+
referencesLoaded: false,
|
| 1037 |
+
isReference: true
|
| 1038 |
+
});
|
| 1039 |
+
});
|
| 1040 |
+
}
|
| 1041 |
+
});
|
| 1042 |
+
|
| 1043 |
+
updatePapersList();
|
| 1044 |
+
updateStatus();
|
| 1045 |
+
addBotMessage(`β
Welcome back! Restored all paper(s) from your previous session.`);
|
| 1046 |
+
} else if (userData.papers && userData.papers.length > 0) {
|
| 1047 |
+
// Fallback to old format for backward compatibility
|
| 1048 |
+
papers = userData.papers.map((title, index) => ({
|
| 1049 |
+
id: Date.now() + index,
|
| 1050 |
+
title: title,
|
| 1051 |
+
type: 'restored',
|
| 1052 |
+
hasReferences: false,
|
| 1053 |
+
referencesLoaded: false
|
| 1054 |
+
}));
|
| 1055 |
+
updatePapersList();
|
| 1056 |
+
updateStatus();
|
| 1057 |
+
addBotMessage(`β
Welcome back! Restored ${userData.papers.length} paper(s) from your previous session.`);
|
| 1058 |
+
}
|
| 1059 |
+
|
| 1060 |
+
// Check API key status
|
| 1061 |
+
if (userData.has_api_key) {
|
| 1062 |
+
apiKeyStatusText.textContent = 'API Key: Connected';
|
| 1063 |
+
showApiKeyModalWithOption();
|
| 1064 |
+
} else {
|
| 1065 |
+
// Clear API key input and status for new login session
|
| 1066 |
+
apiKeyInput.value = '';
|
| 1067 |
+
apiKeyStatusText.textContent = 'API Key: Not connected';
|
| 1068 |
+
showApiKeyModal();
|
| 1069 |
+
}
|
| 1070 |
+
} else {
|
| 1071 |
+
// Fallback to normal flow
|
| 1072 |
+
apiKeyInput.value = '';
|
| 1073 |
+
apiKeyStatusText.textContent = 'API Key: Not connected';
|
| 1074 |
+
showApiKeyModal();
|
| 1075 |
+
addBotMessage('β
Login successful! Please enter your GROQ API key to continue.');
|
| 1076 |
+
}
|
| 1077 |
+
} catch (error) {
|
| 1078 |
+
console.error('Error checking user data:', error);
|
| 1079 |
+
// Fallback to normal flow
|
| 1080 |
+
apiKeyInput.value = '';
|
| 1081 |
+
apiKeyStatusText.textContent = 'API Key: Not connected';
|
| 1082 |
+
showApiKeyModal();
|
| 1083 |
+
addBotMessage('β
Login successful! Please enter your GROQ API key to continue.');
|
| 1084 |
+
}
|
| 1085 |
+
}
|
| 1086 |
+
|
| 1087 |
+
function showApiKeyModalWithOption() {
|
| 1088 |
+
if (!isLoggedIn) {
|
| 1089 |
+
showLoginModal();
|
| 1090 |
+
return;
|
| 1091 |
+
}
|
| 1092 |
+
|
| 1093 |
+
// Update modal to show option for existing API key
|
| 1094 |
+
const apiKeyForm = document.querySelector('.api-key-form');
|
| 1095 |
+
apiKeyForm.innerHTML = `
|
| 1096 |
+
<h2>π API Key Options</h2>
|
| 1097 |
+
<p>You have an existing GROQ API key. Choose an option:</p>
|
| 1098 |
+
<button type="button" class="api-key-submit" onclick="useExistingApiKey()" style="margin-bottom: 15px; width: 100%;">
|
| 1099 |
+
Use Existing API Key
|
| 1100 |
+
</button>
|
| 1101 |
+
<button type="button" class="api-key-submit" onclick="enterNewApiKey()" style="background: rgba(102, 126, 234, 0.1); color: #667eea; width: 100%;">
|
| 1102 |
+
Enter New API Key
|
| 1103 |
+
</button>
|
| 1104 |
+
`;
|
| 1105 |
+
|
| 1106 |
+
apiKeyModal.style.display = 'flex';
|
| 1107 |
+
}
|
| 1108 |
+
|
| 1109 |
+
async function useExistingApiKey() {
|
| 1110 |
+
hideApiKeyModal();
|
| 1111 |
+
addBotMessage('β
Using your existing API key. You can start uploading papers and asking questions!');
|
| 1112 |
+
}
|
| 1113 |
+
|
| 1114 |
+
function enterNewApiKey() {
|
| 1115 |
+
// Reset modal to normal API key entry
|
| 1116 |
+
const apiKeyForm = document.querySelector('.api-key-form');
|
| 1117 |
+
apiKeyForm.innerHTML = `
|
| 1118 |
+
<h2>π Enter GROQ API Key</h2>
|
| 1119 |
+
<p>Please enter your GROQ API key to use the chatbot. Your key will be stored securely in your session.</p>
|
| 1120 |
+
<div class="api-key-input-group">
|
| 1121 |
+
<input type="password" id="apiKeyInput" class="api-key-input" placeholder="Enter your GROQ API key...">
|
| 1122 |
+
<button type="button" class="toggle-visibility" onclick="toggleApiKeyVisibility()">ποΈ</button>
|
| 1123 |
+
</div>
|
| 1124 |
+
<button id="apiKeySubmit" class="api-key-submit">Connect</button>
|
| 1125 |
+
`;
|
| 1126 |
+
|
| 1127 |
+
// Re-initialize the input and submit button references
|
| 1128 |
+
const newApiKeyInput = document.getElementById('apiKeyInput');
|
| 1129 |
+
const newApiKeySubmit = document.getElementById('apiKeySubmit');
|
| 1130 |
+
newApiKeyInput.value = '';
|
| 1131 |
+
newApiKeyInput.focus();
|
| 1132 |
+
|
| 1133 |
+
// Re-add event listeners
|
| 1134 |
+
newApiKeySubmit.addEventListener('click', setApiKey);
|
| 1135 |
+
newApiKeyInput.addEventListener('keypress', (e) => {
|
| 1136 |
+
if (e.key === 'Enter') setApiKey();
|
| 1137 |
+
});
|
| 1138 |
}
|
| 1139 |
|
| 1140 |
function logout() {
|
|
|
|
| 1164 |
|
| 1165 |
// β
API Key Functions
|
| 1166 |
function toggleApiKeyVisibility() {
|
| 1167 |
+
// Always get the current API key input element dynamically
|
| 1168 |
+
const currentApiKeyInput = document.getElementById('apiKeyInput');
|
| 1169 |
const button = document.querySelector('.toggle-visibility');
|
| 1170 |
+
|
| 1171 |
+
if (!currentApiKeyInput) return;
|
| 1172 |
+
|
| 1173 |
+
if (currentApiKeyInput.type === 'password') {
|
| 1174 |
+
currentApiKeyInput.type = 'text';
|
| 1175 |
button.textContent = 'π';
|
| 1176 |
} else {
|
| 1177 |
+
currentApiKeyInput.type = 'password';
|
| 1178 |
button.textContent = 'ποΈ';
|
| 1179 |
}
|
| 1180 |
}
|
|
|
|
| 1185 |
return;
|
| 1186 |
}
|
| 1187 |
// Clear the API key input for new users
|
| 1188 |
+
const currentApiKeyInput = document.getElementById('apiKeyInput');
|
| 1189 |
+
if (currentApiKeyInput) {
|
| 1190 |
+
currentApiKeyInput.value = '';
|
| 1191 |
+
}
|
| 1192 |
apiKeyModal.style.display = 'flex';
|
| 1193 |
+
if (currentApiKeyInput) {
|
| 1194 |
+
currentApiKeyInput.focus();
|
| 1195 |
+
}
|
| 1196 |
}
|
| 1197 |
|
| 1198 |
function hideApiKeyModal() {
|
|
|
|
| 1200 |
}
|
| 1201 |
|
| 1202 |
async function setApiKey() {
|
| 1203 |
+
// Always get the current API key input element dynamically
|
| 1204 |
+
const currentApiKeyInput = document.getElementById('apiKeyInput');
|
| 1205 |
+
const currentApiKeySubmit = document.getElementById('apiKeySubmit');
|
| 1206 |
+
|
| 1207 |
+
if (!currentApiKeyInput) {
|
| 1208 |
+
alert('API key input not found');
|
| 1209 |
+
return;
|
| 1210 |
+
}
|
| 1211 |
+
|
| 1212 |
+
const key = currentApiKeyInput.value.trim();
|
| 1213 |
if (!key) {
|
| 1214 |
alert('Please enter a valid API key');
|
| 1215 |
return;
|
| 1216 |
}
|
| 1217 |
|
| 1218 |
+
currentApiKeySubmit.disabled = true;
|
| 1219 |
+
currentApiKeySubmit.textContent = 'Connecting...';
|
| 1220 |
|
| 1221 |
try {
|
| 1222 |
// Send API key to backend for ephemeral storage
|
|
|
|
| 1240 |
console.error('API key setup error:', error);
|
| 1241 |
addBotMessage(`β Failed to connect API key: ${error.message}`);
|
| 1242 |
} finally {
|
| 1243 |
+
currentApiKeySubmit.disabled = false;
|
| 1244 |
+
currentApiKeySubmit.textContent = 'Connect';
|
| 1245 |
}
|
| 1246 |
}
|
| 1247 |
|
|
|
|
| 1460 |
return;
|
| 1461 |
}
|
| 1462 |
|
| 1463 |
+
setStatus('processing', 'Loading references...(might take longer)');
|
| 1464 |
const formData = new FormData();
|
| 1465 |
formData.append("index", paperIndex.toString());
|
| 1466 |
|
|
|
|
| 1545 |
if (paper.isReference) {
|
| 1546 |
div.style.borderLeft = '4px solid #28a745';
|
| 1547 |
div.style.backgroundColor = 'rgba(40, 167, 69, 0.05)';
|
| 1548 |
+
} else if (paper.type === 'restored') {
|
| 1549 |
+
div.style.borderLeft = '4px solid #17a2b8';
|
| 1550 |
+
div.style.backgroundColor = 'rgba(23, 162, 184, 0.05)';
|
| 1551 |
}
|
| 1552 |
|
| 1553 |
div.innerHTML = `
|
| 1554 |
<div class="paper-title">
|
| 1555 |
+
${paper.isReference ? 'π ' : ''}${paper.type === 'restored' ? 'π ' : ''}${paper.title}
|
| 1556 |
${paper.isReference ? ' <small style="color: #6c757d;">(Reference)</small>' : ''}
|
| 1557 |
+
${paper.type === 'restored' ? ' <small style="color: #17a2b8;">(Restored)</small>' : ''}
|
| 1558 |
</div>
|
| 1559 |
<div class="paper-actions">
|
| 1560 |
${!paper.isReference ? `
|
|
|
|
| 1620 |
window.addReferences = addReferences;
|
| 1621 |
window.logout = logout;
|
| 1622 |
window.toggleAuthMode = toggleAuthMode;
|
| 1623 |
+
window.useExistingApiKey = useExistingApiKey;
|
| 1624 |
+
window.enterNewApiKey = enterNewApiKey;
|
| 1625 |
</script>
|
| 1626 |
</body>
|
| 1627 |
</html>
|