Spaces:
Sleeping
Sleeping
sachin1801
added api routes, changes to input pages, db creationg + token mapping, history page created, batch support for csv + fasta files
923926c | /** | |
| * Token management utilities for user identification. | |
| * Tokens are stored in localStorage and used to track job history. | |
| * Format: tok_xxxxxxxxxxxx (12 random alphanumeric characters) | |
| */ | |
| const TOKEN_KEY = 'splicing_access_token'; | |
| const TOKEN_PREFIX = 'tok_'; | |
| const TOKEN_RANDOM_LENGTH = 12; | |
| /** | |
| * Generate a random token. | |
| * @returns {string} Token in format tok_xxxxxxxxxxxx | |
| */ | |
| function generateToken() { | |
| const chars = 'abcdefghijklmnopqrstuvwxyz0123456789'; | |
| let result = TOKEN_PREFIX; | |
| for (let i = 0; i < TOKEN_RANDOM_LENGTH; i++) { | |
| result += chars.charAt(Math.floor(Math.random() * chars.length)); | |
| } | |
| return result; | |
| } | |
| /** | |
| * Validate token format. | |
| * @param {string} token - Token to validate | |
| * @returns {boolean} True if valid format | |
| */ | |
| function isValidToken(token) { | |
| const pattern = new RegExp(`^${TOKEN_PREFIX}[a-z0-9]{${TOKEN_RANDOM_LENGTH}}$`); | |
| return pattern.test(token); | |
| } | |
| /** | |
| * Get current token from localStorage, or generate new one. | |
| * @returns {string} The access token | |
| */ | |
| function getOrCreateToken() { | |
| let token = localStorage.getItem(TOKEN_KEY); | |
| if (!token || !isValidToken(token)) { | |
| token = generateToken(); | |
| localStorage.setItem(TOKEN_KEY, token); | |
| } | |
| return token; | |
| } | |
| /** | |
| * Get current token from localStorage (may be null). | |
| * @returns {string|null} The access token or null | |
| */ | |
| function getToken() { | |
| return localStorage.getItem(TOKEN_KEY); | |
| } | |
| /** | |
| * Set a new token in localStorage. | |
| * @param {string} newToken - The new token to set | |
| * @returns {boolean} True if successfully set | |
| */ | |
| function setToken(newToken) { | |
| if (!isValidToken(newToken)) { | |
| return false; | |
| } | |
| localStorage.setItem(TOKEN_KEY, newToken); | |
| return true; | |
| } | |
| /** | |
| * Clear the token from localStorage. | |
| */ | |
| function clearToken() { | |
| localStorage.removeItem(TOKEN_KEY); | |
| } | |
| /** | |
| * Copy token to clipboard. | |
| * @returns {Promise<boolean>} True if successfully copied | |
| */ | |
| async function copyTokenToClipboard() { | |
| const token = getToken(); | |
| if (!token) return false; | |
| try { | |
| await navigator.clipboard.writeText(token); | |
| return true; | |
| } catch (err) { | |
| console.error('Failed to copy token:', err); | |
| return false; | |
| } | |
| } | |
| /** | |
| * Initialize token display in the UI. | |
| * Call this on page load to show current token. | |
| */ | |
| function initTokenDisplay() { | |
| const token = getOrCreateToken(); | |
| // Update token display element if it exists | |
| const displayEl = document.getElementById('token-display'); | |
| if (displayEl) { | |
| displayEl.textContent = token; | |
| displayEl.title = 'Double-click to edit'; | |
| displayEl.style.cursor = 'pointer'; | |
| // Double-click to edit inline | |
| displayEl.addEventListener('dblclick', () => { | |
| startInlineEdit(displayEl); | |
| }); | |
| } | |
| // Setup copy button | |
| const copyBtn = document.getElementById('token-copy-btn'); | |
| if (copyBtn) { | |
| copyBtn.addEventListener('click', async () => { | |
| const success = await copyTokenToClipboard(); | |
| if (success) { | |
| const originalText = copyBtn.textContent; | |
| copyBtn.textContent = 'Copied!'; | |
| setTimeout(() => { | |
| copyBtn.textContent = originalText; | |
| }, 2000); | |
| } | |
| }); | |
| } | |
| return token; | |
| } | |
| /** | |
| * Start inline editing of the token display. | |
| * @param {HTMLElement} displayEl - The token display element | |
| */ | |
| function startInlineEdit(displayEl) { | |
| const currentToken = displayEl.textContent; | |
| const originalBg = displayEl.style.backgroundColor; | |
| // Make editable | |
| displayEl.contentEditable = true; | |
| displayEl.style.backgroundColor = '#fff'; | |
| displayEl.style.outline = '2px solid #3b82f6'; | |
| displayEl.style.outlineOffset = '1px'; | |
| displayEl.focus(); | |
| // Select all text | |
| const range = document.createRange(); | |
| range.selectNodeContents(displayEl); | |
| const selection = window.getSelection(); | |
| selection.removeAllRanges(); | |
| selection.addRange(range); | |
| // Handle blur (save on click away) | |
| const handleBlur = () => { | |
| finishInlineEdit(displayEl, currentToken, originalBg); | |
| }; | |
| // Handle keydown (Enter to save, Escape to cancel) | |
| const handleKeydown = (e) => { | |
| if (e.key === 'Enter') { | |
| e.preventDefault(); | |
| displayEl.blur(); | |
| } else if (e.key === 'Escape') { | |
| displayEl.textContent = currentToken; | |
| displayEl.blur(); | |
| } | |
| }; | |
| displayEl.addEventListener('blur', handleBlur, { once: true }); | |
| displayEl.addEventListener('keydown', handleKeydown); | |
| // Remove keydown listener after blur | |
| displayEl.addEventListener('blur', () => { | |
| displayEl.removeEventListener('keydown', handleKeydown); | |
| }, { once: true }); | |
| } | |
| /** | |
| * Finish inline editing and save if valid. | |
| * @param {HTMLElement} displayEl - The token display element | |
| * @param {string} originalToken - The original token before editing | |
| * @param {string} originalBg - The original background color | |
| */ | |
| function finishInlineEdit(displayEl, originalToken, originalBg) { | |
| displayEl.contentEditable = false; | |
| displayEl.style.backgroundColor = originalBg; | |
| displayEl.style.outline = ''; | |
| displayEl.style.outlineOffset = ''; | |
| const newToken = displayEl.textContent.trim(); | |
| if (newToken === originalToken) { | |
| // No change | |
| return; | |
| } | |
| if (setToken(newToken)) { | |
| displayEl.textContent = newToken; | |
| } else { | |
| // Invalid token, revert | |
| displayEl.textContent = originalToken; | |
| alert('Invalid token format. Token must be: tok_ followed by 12 lowercase letters/numbers'); | |
| } | |
| } | |
| // Export functions for use in other scripts | |
| window.TokenManager = { | |
| generateToken, | |
| isValidToken, | |
| getOrCreateToken, | |
| getToken, | |
| setToken, | |
| clearToken, | |
| copyTokenToClipboard, | |
| initTokenDisplay, | |
| TOKEN_KEY, | |
| }; | |