// Smartboard JavaScript utilities class SmartboardAPI { constructor(csrfToken) { this.csrfToken = csrfToken } async request(url, options = {}) { const defaultOptions = { headers: { "Content-Type": "application/json", "X-CSRFToken": this.csrfToken, }, } const mergedOptions = { ...defaultOptions, ...options, headers: { ...defaultOptions.headers, ...options.headers, }, } try { const response = await fetch(url, mergedOptions) const data = await response.json() if (!response.ok) { throw new Error(data.error || "API request failed") } return data } catch (error) { console.error("API Error:", error) throw error } } async uploadPDF(formData) { return await fetch("/api/upload-pdf/", { method: "POST", body: formData, headers: { "X-CSRFToken": this.csrfToken, }, }) } async getPages(documentId) { return await this.request(`/api/document/${documentId}/pages/`) } async getBlocks(pageId) { return await this.request(`/api/page/${pageId}/blocks/`) } async createBlock(blockData) { return await this.request("/api/blocks/create/", { method: "POST", body: JSON.stringify(blockData), }) } async updateBlock(blockId, updateData) { return await this.request(`/api/blocks/${blockId}/update/`, { method: "PUT", body: JSON.stringify(updateData), }) } async deleteBlock(blockId) { return await this.request(`/api/blocks/${blockId}/delete/`, { method: "DELETE", }) } async uploadBlockFile(blockId, file) { const formData = new FormData() formData.append("file", file) return await fetch(`/api/blocks/${blockId}/upload-file/`, { method: "POST", body: formData, headers: { "X-CSRFToken": this.csrfToken, }, }) } } // Utility functions function showNotification(message, type = "info") { // Create notification element const notification = document.createElement("div") notification.className = `fixed top-4 right-4 z-50 p-4 rounded-lg shadow-lg max-w-sm ${ type === "success" ? "bg-green-500 text-white" : type === "error" ? "bg-red-500 text-white" : type === "warning" ? "bg-yellow-500 text-black" : "bg-blue-500 text-white" }` notification.innerHTML = `
${message}
` document.body.appendChild(notification) // Auto remove after 5 seconds setTimeout(() => { if (notification.parentElement) { notification.remove() } }, 5000) } function formatFileSize(bytes) { if (bytes === 0) return "0 Bytes" const k = 1024 const sizes = ["Bytes", "KB", "MB", "GB"] const i = Math.floor(Math.log(bytes) / Math.log(k)) return Number.parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + " " + sizes[i] } function debounce(func, wait) { let timeout return function executedFunction(...args) { const later = () => { clearTimeout(timeout) func(...args) } clearTimeout(timeout) timeout = setTimeout(later, wait) } } // Export for use in templates window.SmartboardAPI = SmartboardAPI window.showNotification = showNotification window.formatFileSize = formatFileSize window.debounce = debounce