UNPKG

revit-journal-assist

Version:

A web-based interface for viewing Autodesk Revit journal logs

240 lines (197 loc) 9.05 kB
// Initialize socket connection const socket = io(); // DOM elements const fileTree = document.getElementById('fileTree'); const journalContent = document.getElementById('journalContent'); const currentFileElement = document.getElementById('currentFile'); const downloadBtn = document.getElementById('downloadBtn'); const loadingOverlay = document.getElementById('loadingOverlay'); const hostnameElement = document.getElementById('hostname'); const localIPElement = document.getElementById('localIP'); // Global variables let currentFilePath = null; // Display hostname hostnameElement.textContent = `Connected to: ${window.location.hostname}`; // Get and display local IP address async function getLocalIP() { try { // Check if we're already using an IP address (not localhost) if (window.location.hostname !== 'localhost' && /^(\d{1,3}\.){3}\d{1,3}$/.test(window.location.hostname)) { localIPElement.innerHTML = `<i class="fas fa-network-wired"></i> Remote access: <a href="http://${window.location.hostname}:${window.location.port}" target="_blank">${window.location.hostname}:${window.location.port}</a>`; return; } // Ask server for local IP address via socket.io socket.emit('getLocalIP'); socket.once('localIP', (ip) => { if (ip) { localIPElement.innerHTML = `<i class="fas fa-network-wired"></i> Remote access: <a href="http://${ip}:${window.location.port}" target="_blank">${ip}:${window.location.port}</a>`; } }); } catch (error) { console.error('Error getting local IP:', error); } } // Load user directories async function loadUsers() { try { const response = await fetch('/api/users'); const users = await response.json(); fileTree.innerHTML = ''; if (users.length === 0) { fileTree.innerHTML = '<div class="loading">No users found</div>'; return; } // Create user folders in the file tree users.forEach(user => { const userItem = createTreeItem(user, 'fas fa-user', async () => { const userChildren = userItem.querySelector('.tree-children'); if (userItem.classList.contains('expanded')) { userItem.classList.remove('expanded'); } else { userItem.classList.add('expanded'); // Only load Revit versions if not already loaded if (userChildren.children.length === 0) { userChildren.innerHTML = '<div class="loading">Loading Revit versions...</div>'; await loadRevitVersions(user, userChildren); } } }); fileTree.appendChild(userItem); }); } catch (error) { console.error('Error loading users:', error); fileTree.innerHTML = '<div class="loading">Error loading users</div>'; } } // Load Revit versions for a specific user async function loadRevitVersions(user, parentElement) { try { const response = await fetch(`/api/user/${user}/revit`); const versions = await response.json(); parentElement.innerHTML = ''; if (versions.length === 0) { parentElement.innerHTML = '<div class="loading">No Revit versions found</div>'; return; } // Create Revit version folders in the file tree versions.forEach(version => { const versionName = version.version.replace('Revit ', ''); const versionItem = createTreeItem(versionName, 'fas fa-folder', async () => { const versionChildren = versionItem.querySelector('.tree-children'); if (versionItem.classList.contains('expanded')) { versionItem.classList.remove('expanded'); } else { versionItem.classList.add('expanded'); // Only load journal files if not already loaded if (versionChildren.children.length === 0) { versionChildren.innerHTML = '<div class="loading">Loading journal files...</div>'; await loadJournalFiles(user, versionName, versionChildren); } } }); parentElement.appendChild(versionItem); }); } catch (error) { console.error('Error loading Revit versions:', error); parentElement.innerHTML = '<div class="loading">Error loading Revit versions</div>'; } } // Load journal files for a specific Revit version async function loadJournalFiles(user, version, parentElement) { try { const response = await fetch(`/api/user/${user}/revit/${version}`); const files = await response.json(); parentElement.innerHTML = ''; if (files.length === 0) { parentElement.innerHTML = '<div class="loading">No journal files found</div>'; return; } // Create journal file items in the file tree files.forEach(file => { const fileItem = createTreeItem(file.name, 'fas fa-file-alt', () => { // Deselect previously selected item const selected = fileTree.querySelector('.selected'); if (selected) selected.classList.remove('selected'); // Select current item fileItem.classList.add('selected'); // Show loading overlay loadingOverlay.style.display = 'flex'; // Load journal file content loadJournalContent(file.path, file.name); }); // Add file info const fileInfo = document.createElement('div'); fileInfo.className = 'file-info'; fileInfo.innerHTML = ` <span>Size: ${formatFileSize(file.size)}</span> <span>Modified: ${new Date(file.modified).toLocaleDateString()}</span> `; fileItem.appendChild(fileInfo); parentElement.appendChild(fileItem); }); } catch (error) { console.error('Error loading journal files:', error); parentElement.innerHTML = '<div class="loading">Error loading journal files</div>'; } } // Load journal file content async function loadJournalContent(filePath, fileName) { try { const response = await fetch(`/api/journal?path=${encodeURIComponent(filePath)}`); if (!response.ok) { throw new Error(`Error: ${response.status} ${response.statusText}`); } const content = await response.text(); // Update UI currentFileElement.textContent = fileName; journalContent.innerHTML = ''; journalContent.textContent = content; // Enable download button downloadBtn.disabled = false; currentFilePath = filePath; } catch (error) { console.error('Error loading journal content:', error); journalContent.innerHTML = `<div class="placeholder">Error loading file: ${error.message}</div>`; // Disable download button downloadBtn.disabled = true; currentFilePath = null; } finally { // Hide loading overlay loadingOverlay.style.display = 'none'; } } // Create a tree item with icon, label, and click handler function createTreeItem(label, iconClass, clickHandler) { const item = document.createElement('div'); item.className = 'tree-item'; const labelContainer = document.createElement('div'); labelContainer.className = 'tree-label'; labelContainer.innerHTML = `<i class="${iconClass} icon"></i><span class="label">${label}</span>`; const children = document.createElement('div'); children.className = 'tree-children'; item.appendChild(labelContainer); item.appendChild(children); if (clickHandler) { labelContainer.addEventListener('click', clickHandler); } return item; } // Format file size to human-readable format function formatFileSize(bytes) { if (bytes < 1024) return bytes + ' B'; if (bytes < 1024 * 1024) return (bytes / 1024).toFixed(1) + ' KB'; if (bytes < 1024 * 1024 * 1024) return (bytes / (1024 * 1024)).toFixed(1) + ' MB'; return (bytes / (1024 * 1024 * 1024)).toFixed(1) + ' GB'; } // Download button event handler downloadBtn.addEventListener('click', () => { if (currentFilePath) { window.open(`/api/download?path=${encodeURIComponent(currentFilePath)}`); } }); // Initialize the application document.addEventListener('DOMContentLoaded', () => { loadUsers(); getLocalIP(); });