diff --git a/static/js/avatar-preview.js b/static/js/avatar-preview.js index 907a8c2..0c73091 100644 --- a/static/js/avatar-preview.js +++ b/static/js/avatar-preview.js @@ -1,3 +1,18 @@ +/** + * @fileoverview Provides avatar image preview functionality. + * This file handles: + * - File selection event handling + * - Image preview generation + * - Real-time avatar preview updates + */ + +/** + * Generates a preview of the selected avatar image. + * Reads the selected file and updates the preview image element. + * @function + * @param {Event} event - The file input change event + * @param {FileList} event.target.files - The list of selected files + */ function previewAvatar(event) { const [file] = event.target.files; if (file) { diff --git a/static/js/chat-manager.js b/static/js/chat-manager.js index e0c5476..5980f27 100644 --- a/static/js/chat-manager.js +++ b/static/js/chat-manager.js @@ -1,9 +1,33 @@ +/** + * @fileoverview Manages global chat state and polling functionality. + * This file implements a singleton ChatManager that handles: + * - Message polling and state management + * - New message processing and event triggering + * - Connection state tracking + * - Resource cleanup + */ + // Global state and polling management if (typeof window.ChatManager === 'undefined') { window.ChatManager = (function() { let instance = null; let pollInterval = null; + /** + * @typedef {Object} ConnectionState + * @property {boolean} hasJoined - Whether the user has joined the conversation + * @property {boolean} isConnected - Current connection status + * @property {number|null} lastMessageId - ID of the last received message + * @property {number} pollAttempts - Number of failed polling attempts + */ + + /** + * @typedef {Object} ChatState + * @property {Set} addedMessageIds - Set of message IDs that have been processed + * @property {Set} messageQueue - Queue of messages waiting to be processed + * @property {ConnectionState} connectionState - Current connection state + */ + const state = { addedMessageIds: new Set(), messageQueue: new Set(), @@ -15,6 +39,13 @@ if (typeof window.ChatManager === 'undefined') { } }; + /** + * Initializes a new ChatManager instance for a conversation. + * Sets up message tracking and starts polling for new messages. + * @function + * @param {string} conversationId - The ID of the conversation to manage + * @returns {Object} The ChatManager instance + */ function init(conversationId) { if (instance) { console.log('[ChatManager] Instance already exists, returning existing instance'); @@ -47,6 +78,12 @@ if (typeof window.ChatManager === 'undefined') { return instance; } + /** + * Starts polling for new messages in the conversation. + * Polls every 3 seconds and performs an initial fetch. + * @function + * @param {string} conversationId - The ID of the conversation to poll + */ function startPolling(conversationId) { console.log('[ChatManager] Starting polling for conversation:', conversationId); @@ -67,6 +104,12 @@ if (typeof window.ChatManager === 'undefined') { fetchNewMessages(conversationId); } + /** + * Fetches new messages from the server. + * Uses the last message ID to only fetch new messages. + * @function + * @param {string} conversationId - The ID of the conversation to fetch messages from + */ function fetchNewMessages(conversationId) { const url = `/conversations/${conversationId}/messages`; const params = new URLSearchParams(); @@ -107,6 +150,12 @@ if (typeof window.ChatManager === 'undefined') { }); } + /** + * Processes new messages and triggers events for each new message. + * Updates the last message ID and tracks processed messages. + * @function + * @param {Array} messages - Array of new message objects to process + */ function processNewMessages(messages) { console.log('[ChatManager] Processing new messages:', { messageCount: messages.length, @@ -133,6 +182,11 @@ if (typeof window.ChatManager === 'undefined') { }); } + /** + * Cleans up polling resources and resets the instance. + * Should be called when the chat is no longer needed. + * @function + */ function cleanup() { console.log('[ChatManager] Cleaning up polling'); if (pollInterval) { @@ -143,6 +197,12 @@ if (typeof window.ChatManager === 'undefined') { } return { + /** + * Gets or creates a ChatManager instance for a conversation. + * @function + * @param {string} conversationId - The ID of the conversation to manage + * @returns {Object} The ChatManager instance + */ getInstance: function(conversationId) { if (!instance) { instance = init(conversationId); diff --git a/static/js/color-logger.js b/static/js/color-logger.js index 8d3ad2f..76cbec2 100644 --- a/static/js/color-logger.js +++ b/static/js/color-logger.js @@ -1,4 +1,22 @@ +/** + * @fileoverview Provides logging functionality for CSS color variables. + * This file handles: + * - Logging of base color loading status + * - Logging of CSS file loading status + * - Logging of primary and secondary color values + */ + +// Log initial base colors loading console.log('[CSS] Base colors loaded'); + +/** + * Logs CSS color information when the DOM is fully loaded. + * Reports: + * - CSS files loading status + * - Primary color value from CSS variables + * - Secondary color value from CSS variables + * @function + */ document.addEventListener('DOMContentLoaded', function() { console.log('[CSS] All CSS files loaded'); console.log('[CSS] Primary color:', getComputedStyle(document.documentElement).getPropertyValue('--primary-color').trim()); diff --git a/static/js/contacts-filter.js b/static/js/contacts-filter.js index 5fead51..5d851e6 100644 --- a/static/js/contacts-filter.js +++ b/static/js/contacts-filter.js @@ -1,4 +1,21 @@ -// Debounce function +/** + * @fileoverview Manages the contacts filtering functionality. + * This file handles: + * - Contact search with debounced input + * - Filter form submission + * - Search state persistence + * - Filter clearing functionality + */ + +/** + * Creates a debounced version of a function that delays its execution + * until after a specified wait time has elapsed since the last time it was invoked. + * This helps prevent excessive form submissions during rapid user input. + * @function + * @param {Function} func - The function to debounce + * @param {number} wait - The number of milliseconds to delay (300ms default for search) + * @returns {Function} A debounced version of the provided function + */ function debounce(func, wait) { let timeout; return function(...args) { @@ -7,7 +24,14 @@ function debounce(func, wait) { }; } -// Initialize filter functionality +/** + * Initializes the contacts filter functionality when the DOM is loaded. + * Sets up: + * - Auto-submit on select changes + * - Debounced search input with cursor position persistence + * - Filter clearing functionality + * @function + */ document.addEventListener('DOMContentLoaded', function() { // Auto-submit the form on select change document.querySelectorAll('#filterForm select').forEach(function(el) { @@ -41,7 +65,11 @@ document.addEventListener('DOMContentLoaded', function() { } } - // Clear button resets all filters and submits the form + /** + * Handles the clear filters button click. + * Resets all filter inputs and submits the form. + * @event + */ document.getElementById('clearFilters').addEventListener('click', function() { document.querySelector('#filterForm input[name="search"]').value = ''; document.querySelector('#filterForm select[name="role"]').selectedIndex = 0; diff --git a/static/js/conversation.js b/static/js/conversation.js index df55459..061ab0e 100644 --- a/static/js/conversation.js +++ b/static/js/conversation.js @@ -1,4 +1,23 @@ -// Initialize chat when document is ready +/** + * @fileoverview Manages the real-time conversation functionality. + * This file handles: + * - Chat message display and management + * - Message submission with file attachments + * - Real-time message updates + * - Chat state management + * - UI interactions and animations + */ + +/** + * Initializes the chat functionality when the document is ready. + * Sets up: + * - Chat state and message tracking + * - Message display and submission + * - File attachment handling + * - Real-time message updates + * - Cleanup on page unload + * @function + */ $(document).ready(function() { const conversationId = window.conversationId; // Set this in the template const currentUserId = window.currentUserId; // Set this in the template @@ -10,7 +29,19 @@ $(document).ready(function() { // Keep track of messages we've already displayed const displayedMessageIds = new Set(); - // Function to append a new message to the chat + /** + * Appends a new message to the chat interface. + * Handles message formatting, attachments, and UI updates. + * @function + * @param {Object} message - The message object to append + * @param {string} message.id - The unique message ID + * @param {string} message.content - The message content + * @param {string} message.sender_id - The ID of the message sender + * @param {string} message.sender_name - The name of the message sender + * @param {string} message.sender_avatar - The avatar URL of the sender + * @param {string} message.created_at - The message creation timestamp + * @param {Array} [message.attachments] - Array of file attachments + */ function appendMessage(message) { console.log('[Conversation] Attempting to append message:', { messageId: message.id, @@ -79,14 +110,23 @@ $(document).ready(function() { } }); - // Scroll to bottom of chat messages + /** + * Scrolls the chat window to the bottom. + * @function + */ function scrollToBottom() { const chatMessages = document.getElementById('chatMessages'); chatMessages.scrollTop = chatMessages.scrollHeight; } scrollToBottom(); - // Listen for new messages + /** + * Event handler for new messages. + * Appends new messages to the chat when received. + * @event + * @param {Event} event - The event object + * @param {Object} message - The new message object + */ $(document).on('new_message', function(event, message) { console.log('[Conversation] Received new_message event:', { messageId: message.id, @@ -96,7 +136,11 @@ $(document).ready(function() { appendMessage(message); }); - // Handle file selection + /** + * Handles file selection for message attachments. + * Updates the UI to show selected files. + * @event + */ $('#fileInput').on('change', function() { const files = Array.from(this.files); if (files.length > 0) { @@ -107,7 +151,14 @@ $(document).ready(function() { } }); - // Handle message form submission + /** + * Handles message form submission. + * Processes text messages and file attachments. + * Manages submission state and UI feedback. + * @event + * @param {Event} e - The form submission event + * @returns {boolean} false to prevent default form submission + */ let isSubmitting = false; $('#messageForm').off('submit').on('submit', function(e) { e.preventDefault(); @@ -202,7 +253,10 @@ $(document).ready(function() { return false; }); - // Clean up on page unload + /** + * Cleans up chat resources when the page is unloaded. + * @event + */ $(window).on('beforeunload', function() { console.log('[Conversation] Cleaning up on page unload'); chat.cleanup(); diff --git a/static/js/conversations-list.js b/static/js/conversations-list.js index 76da653..ddbbbaf 100644 --- a/static/js/conversations-list.js +++ b/static/js/conversations-list.js @@ -1,4 +1,20 @@ -// Debounce function +/** + * @fileoverview Manages the conversations list functionality. + * This file handles: + * - Conversation search with debounced input + * - Search form submission + * - Clear filter functionality + */ + +/** + * Creates a debounced version of a function that delays its execution + * until after a specified wait time has elapsed since the last time it was invoked. + * This helps prevent excessive form submissions during rapid user input. + * @function + * @param {Function} func - The function to debounce + * @param {number} wait - The number of milliseconds to delay (300ms default for search) + * @returns {Function} A debounced version of the provided function + */ function debounce(func, wait) { let timeout; return function(...args) { @@ -7,6 +23,13 @@ function debounce(func, wait) { }; } +/** + * Initializes the conversations list functionality when the DOM is loaded. + * Sets up: + * - Search input with debounced form submission (300ms delay) + * - Clear filter button to reset search and refresh results + * @function + */ document.addEventListener('DOMContentLoaded', function() { const searchInput = document.getElementById('conversationSearchInput'); const form = document.getElementById('conversationFilterForm'); diff --git a/static/js/create-conversation.js b/static/js/create-conversation.js index 297e6e7..5364419 100644 --- a/static/js/create-conversation.js +++ b/static/js/create-conversation.js @@ -1,3 +1,20 @@ +/** + * @fileoverview Manages the conversation creation functionality. + * This file handles: + * - User selection interface using Select2 + * - Member management for new conversations + * - Form submission with member data + * - UI updates and validation + */ + +/** + * Initializes conversation creation functionality when the document is ready. + * Sets up: + * - Select2 dropdown for user selection + * - Member tracking and management + * - Form handling + * @function + */ $(document).ready(function() { $('.select2').select2({ theme: 'bootstrap-5', @@ -11,14 +28,22 @@ $(document).ready(function() { var creatorId = document.querySelector('.member-row').dataset.userId; addedMembers.add(creatorId); - // Function to show alert modal + /** + * Shows an alert modal with the specified message. + * @function + * @param {string} message - The message to display in the alert modal + */ function showAlert(message) { $('#alertModalMessage').text(message); var alertModal = new bootstrap.Modal(document.getElementById('alertModal')); alertModal.show(); } - // Handle Add Member button click + /** + * Handles adding a new member to the conversation. + * Validates the selection and updates the UI accordingly. + * @event + */ $('#addMemberBtn').click(function() { var selectedUserId = $('#user_id').val(); var selectedUserName = $('#user_id option:selected').text(); @@ -69,6 +94,11 @@ $(document).ready(function() { updateHiddenInputs(); }); + /** + * Updates the hidden form inputs with the current member list. + * Removes existing member inputs and adds new ones for each current member. + * @function + */ function updateHiddenInputs() { // Remove any existing members inputs $('#conversationForm input[name="members"]').remove(); diff --git a/static/js/debugging.js b/static/js/debugging.js index 3c59623..498c503 100644 --- a/static/js/debugging.js +++ b/static/js/debugging.js @@ -1,3 +1,12 @@ +/** + * @fileoverview Provides debugging and maintenance functionality for the application. + * This file handles: + * - File system synchronization + * - Database state verification + * - Orphaned record cleanup + * - Mismatch detection and reporting + */ + // File system sync functionality document.getElementById('syncFilesBtn').addEventListener('click', async function() { const btn = this; @@ -162,7 +171,13 @@ document.getElementById('cleanupOrphanedBtn').addEventListener('click', async fu } }); -// Helper function to update mismatch sections +/** + * Updates a mismatch section in the UI with verification results. + * Displays counts and detailed information about mismatches. + * @function + * @param {string} sectionId - The ID of the section to update + * @param {Array} items - Array of mismatch items to display + */ function updateMismatchSection(sectionId, items) { const count = document.getElementById(`${sectionId}Count`); const list = document.getElementById(`${sectionId}List`); @@ -211,7 +226,13 @@ function updateMismatchSection(sectionId, items) { `).join(''); } -// Helper function to format file sizes +/** + * Formats a file size in bytes to a human-readable string. + * Converts to appropriate unit (B, KB, MB, GB, TB). + * @function + * @param {number} bytes - The size in bytes + * @returns {string} The formatted size string (e.g., "1.5 MB") + */ function formatSize(bytes) { if (bytes === 0) return '0 B'; const k = 1024; diff --git a/static/js/file-grid.js b/static/js/file-grid.js index 5d1fcfb..36ffc80 100644 --- a/static/js/file-grid.js +++ b/static/js/file-grid.js @@ -1,3 +1,14 @@ +/** + * @fileoverview Manages the file grid view functionality. + * This file handles: + * - File grid and list view rendering + * - File sorting and filtering + * - File operations (star, restore, delete) + * - View preferences + * - Search functionality + * - File details display + */ + let currentView = 'grid'; let lastSelectedIndex = -1; let sortColumn = 'name'; // Set default sort column to name @@ -10,7 +21,12 @@ window.isAdmin = document.body.dataset.isAdmin === 'true'; // Check if we're on the trash page const isTrashPage = window.location.pathname.includes('/trash'); -// Initialize the view and fetch files +/** + * Initializes the file view and fetches files. + * Sets up the preferred view and initial file sorting. + * @async + * @function + */ async function initializeView() { try { const response = await fetch('/api/user/preferred_view'); @@ -31,6 +47,12 @@ async function initializeView() { sortFiles('name'); } +/** + * Toggles between grid and list views. + * Updates the UI and saves the user's view preference. + * @function + * @param {string} view - The view to switch to ('grid' or 'list') + */ function toggleView(view) { currentView = view; const grid = document.getElementById('fileGrid'); @@ -77,6 +99,12 @@ function toggleView(view) { }); } +/** + * Sorts files by the specified column. + * Handles different data types (string, number, date) appropriately. + * @function + * @param {string} column - The column to sort by ('name', 'modified', 'type', 'size', 'auto_delete') + */ function sortFiles(column) { if (sortColumn === column) { sortDirection *= -1; // Toggle direction @@ -102,6 +130,12 @@ function sortFiles(column) { renderFiles(currentFiles); } +/** + * Gets the appropriate icon class for a file based on its extension. + * @function + * @param {string} filename - The name of the file + * @returns {string} The Font Awesome icon class for the file type + */ function getFileIcon(filename) { const extension = filename.split('.').pop().toLowerCase(); @@ -127,6 +161,12 @@ function getFileIcon(filename) { return iconMap[extension] || 'fa-file'; } +/** + * Renders the files in either grid or list view. + * Handles both trash and normal file views with appropriate actions. + * @function + * @param {Array} files - Array of file objects to render + */ function renderFiles(files) { if (!files) return; currentFiles = files; @@ -223,6 +263,12 @@ function renderFiles(files) { } } +/** + * Fetches files from the server. + * Handles both trash and starred file endpoints. + * @async + * @function + */ async function fetchFiles() { try { const endpoint = isTrashPage ? '/api/rooms/trash' : '/api/rooms/starred'; @@ -244,6 +290,11 @@ async function fetchFiles() { } } +/** + * Gets the CSRF token from various possible locations in the DOM. + * @function + * @returns {string} The CSRF token or empty string if not found + */ function getCsrfToken() { // First try to get it from the meta tag const metaTag = document.querySelector('meta[name="csrf-token"]'); @@ -275,6 +326,13 @@ function getCsrfToken() { return ''; } +/** + * Toggles the star status of a file. + * @function + * @param {string} filename - The name of the file + * @param {string} path - The path of the file + * @param {number} roomId - The ID of the room containing the file + */ function toggleStar(filename, path = '', roomId) { const csrfToken = getCsrfToken(); if (!csrfToken) { @@ -308,6 +366,13 @@ function toggleStar(filename, path = '', roomId) { }); } +/** + * Restores a file from the trash. + * @function + * @param {string} filename - The name of the file + * @param {string} path - The path of the file + * @param {number} roomId - The ID of the room containing the file + */ function restoreFile(filename, path = '', roomId) { const csrfToken = getCsrfToken(); if (!csrfToken) { @@ -341,6 +406,13 @@ function restoreFile(filename, path = '', roomId) { }); } +/** + * Shows the permanent delete confirmation modal. + * @function + * @param {string} filename - The name of the file + * @param {string} path - The path of the file + * @param {number} roomId - The ID of the room containing the file + */ function showPermanentDeleteModal(filename, path = '', roomId) { fileToDelete = { filename, path, roomId }; document.getElementById('permanentDeleteItemName').textContent = filename; @@ -348,6 +420,10 @@ function showPermanentDeleteModal(filename, path = '', roomId) { modal.show(); } +/** + * Permanently deletes a file after confirmation. + * @function + */ function permanentDeleteFile() { if (!fileToDelete) return; @@ -405,6 +481,14 @@ function permanentDeleteFile() { }); } +/** + * Navigates to a file or folder. + * @function + * @param {number} roomId - The ID of the room + * @param {string} filename - The name of the file/folder + * @param {string} path - The path of the file/folder + * @param {string} type - The type of item ('file' or 'folder') + */ function navigateToFile(roomId, filename, path, type) { if (type === 'folder') { window.location.href = `/room/${roomId}?path=${encodeURIComponent(path ? path + '/' + filename : filename)}`; @@ -413,11 +497,19 @@ function navigateToFile(roomId, filename, path, type) { } } +/** + * Shows the empty trash confirmation modal. + * @function + */ function showEmptyTrashModal() { const modal = new bootstrap.Modal(document.getElementById('emptyTrashModal')); modal.show(); } +/** + * Empties the trash by permanently deleting all trashed files. + * @function + */ function emptyTrash() { const csrfToken = getCsrfToken(); if (!csrfToken) { @@ -465,6 +557,11 @@ function emptyTrash() { }); } +/** + * Shows the file details modal. + * @function + * @param {number} idx - The index of the file in the currentFiles array + */ function showDetailsModal(idx) { const item = currentFiles[idx]; const icon = item.type === 'folder' @@ -498,6 +595,12 @@ function showDetailsModal(idx) { modal.show(); } +/** + * Formats a date string to a localized format. + * @function + * @param {string} dateString - The date string to format + * @returns {string} The formatted date string + */ function formatDate(dateString) { const date = new Date(dateString); return date.toLocaleString(); diff --git a/static/js/member-management.js b/static/js/member-management.js index d7440bc..8783729 100644 --- a/static/js/member-management.js +++ b/static/js/member-management.js @@ -1,3 +1,21 @@ +/** + * @fileoverview Manages room member management functionality. + * This file handles: + * - User selection interface using Select2 + * - Adding new members to a room + * - Removing existing members + * - Form submission with member data + */ + +/** + * Initializes member management functionality when the document is ready. + * Sets up: + * - Select2 dropdown for user selection + * - Member removal functionality + * - Member addition functionality + * - Form submission handling + * @function + */ $(document).ready(function() { // Initialize Select2 for user selection $('.select2').select2({ @@ -5,13 +23,22 @@ $(document).ready(function() { width: '100%' }); - // Handle member removal + /** + * Handles member removal from the list. + * Removes the member row from the UI when the remove button is clicked. + * @event + */ $(document).on('click', '.btn-remove-member', function() { const memberRow = $(this).closest('.member-row'); memberRow.remove(); }); - // Handle adding new member + /** + * Handles adding a new member to the list. + * Validates the selection and adds the member if not already present. + * Creates a new member row with user details and adds it to the list. + * @event + */ $('#addMemberBtn').on('click', function() { const select = $('#user_id'); const selectedOption = select.find('option:selected'); @@ -52,7 +79,12 @@ $(document).ready(function() { select.val(null).trigger('change'); }); - // Handle form submission + /** + * Handles form submission. + * Collects all member IDs and adds them as hidden inputs to the form. + * @event + * @param {Event} e - The form submission event + */ $('#membersForm').on('submit', function(e) { e.preventDefault(); diff --git a/static/js/room-members.js b/static/js/room-members.js index e67b5d3..198174c 100644 --- a/static/js/room-members.js +++ b/static/js/room-members.js @@ -1,3 +1,18 @@ +/** + * @fileoverview Manages room member functionality and permissions. + * This file handles: + * - User selection interface using Select2 + * - Room member permissions management + * - Auto-saving permission changes + */ + +/** + * Initializes room member functionality when the document is ready. + * Sets up: + * - Select2 dropdown for user selection with Bootstrap 5 theme + * - Auto-save functionality for permission changes + * @function + */ $(document).ready(function() { // Initialize Select2 for user selection $('.select2').select2({ diff --git a/static/js/rooms-list.js b/static/js/rooms-list.js index f78b858..75068ad 100644 --- a/static/js/rooms-list.js +++ b/static/js/rooms-list.js @@ -1,4 +1,20 @@ -// Debounce function +/** + * @fileoverview Manages the rooms list view functionality. + * This file handles: + * - Room list search with debounced input + * - Room filter form submission + * - Clear filter functionality for the rooms list + */ + +/** + * Creates a debounced version of a function that delays its execution + * until after a specified wait time has elapsed since the last time it was invoked. + * This helps prevent excessive form submissions during rapid user input. + * @function + * @param {Function} func - The function to debounce + * @param {number} wait - The number of milliseconds to delay (300ms default for search) + * @returns {Function} A debounced version of the provided function + */ function debounce(func, wait) { let timeout; return function(...args) { @@ -7,6 +23,13 @@ function debounce(func, wait) { }; } +/** + * Initializes the rooms list functionality when the DOM is loaded. + * Sets up event listeners for: + * - Search input with debounced form submission (300ms delay) + * - Clear filter button to reset search and refresh results + * @function + */ document.addEventListener('DOMContentLoaded', function() { const searchInput = document.getElementById('roomSearchInput'); const form = document.getElementById('roomFilterForm'); diff --git a/static/js/rooms.js b/static/js/rooms.js index f78b858..379e7d6 100644 --- a/static/js/rooms.js +++ b/static/js/rooms.js @@ -1,4 +1,19 @@ -// Debounce function +/** + * @fileoverview Manages room search and filtering functionality. + * This file handles: + * - Room search input with debounced submission + * - Clear filter functionality + * - Form submission for room filtering + */ + +/** + * Creates a debounced version of a function that delays its execution + * until after a specified wait time has elapsed since the last time it was invoked. + * @function + * @param {Function} func - The function to debounce + * @param {number} wait - The number of milliseconds to delay + * @returns {Function} A debounced version of the provided function + */ function debounce(func, wait) { let timeout; return function(...args) { @@ -7,6 +22,13 @@ function debounce(func, wait) { }; } +/** + * Initializes room search and filtering functionality when the DOM is loaded. + * Sets up event listeners for: + * - Search input with debounced form submission + * - Clear filter button + * @function + */ document.addEventListener('DOMContentLoaded', function() { const searchInput = document.getElementById('roomSearchInput'); const form = document.getElementById('roomFilterForm'); diff --git a/static/js/rooms/fileManager.js b/static/js/rooms/fileManager.js index 441b525..b290ac3 100644 --- a/static/js/rooms/fileManager.js +++ b/static/js/rooms/fileManager.js @@ -1,4 +1,23 @@ +/** + * @fileoverview Manages file operations and state for the room interface. + * This file handles: + * - File fetching and state management + * - File operations (delete, rename, move, download) + * - File selection and batch operations + * - Star/unstar functionality + * - Navigation and path management + */ + +/** + * @class FileManager + * @classdesc Manages all file-related operations and state in the room interface. + * Handles file operations, selection, and navigation. + */ export class FileManager { + /** + * Creates a new FileManager instance. + * @param {RoomManager} roomManager - The parent RoomManager instance + */ constructor(roomManager) { console.log('[FileManager] Initializing...'); this.roomManager = roomManager; @@ -13,6 +32,12 @@ export class FileManager { console.log('[FileManager] Initialized with roomManager:', roomManager); } + /** + * Fetches files from the server for the current path. + * @async + * @returns {Promise} A promise that resolves with the array of files + * @throws {Error} If the fetch operation fails + */ async fetchFiles() { console.log('[FileManager] Fetching files...'); try { @@ -44,6 +69,13 @@ export class FileManager { } } + /** + * Deletes a file from the server. + * @async + * @param {string} filename - The name of the file to delete + * @param {string} [path=''] - The path of the file to delete + * @throws {Error} If the delete operation fails + */ async deleteFile(filename, path = '') { console.log('[FileManager] Deleting file:', { filename, path }); const csrfToken = document.querySelector('meta[name="csrf-token"]').getAttribute('content'); @@ -90,6 +122,14 @@ export class FileManager { } } + /** + * Renames a file on the server. + * @async + * @param {string} fileId - The ID of the file to rename + * @param {string} newName - The new name for the file + * @returns {Promise} A promise that resolves with the result of the rename operation + * @throws {Error} If the rename operation fails + */ async renameFile(fileId, newName) { console.log('[FileManager] Renaming file:', { fileId, newName }); try { @@ -127,6 +167,14 @@ export class FileManager { } } + /** + * Moves a file to a new location. + * @async + * @param {string} fileId - The ID of the file to move + * @param {string} targetPath - The target path to move the file to + * @returns {Promise} A promise that resolves with the result of the move operation + * @throws {Error} If the move operation fails + */ async moveFile(fileId, targetPath) { console.log('[FileManager] Starting moveFile...'); console.log('[FileManager] Parameters:', { fileId, targetPath }); @@ -178,6 +226,11 @@ export class FileManager { } } + /** + * Handles the confirmed move operation after user confirmation. + * @async + * @throws {Error} If the move operation fails + */ async moveFileConfirmed() { console.log('[FileManager] Starting moveFileConfirmed...'); console.log('[FileManager] Current state:', { @@ -258,6 +311,13 @@ export class FileManager { } } + /** + * Toggles the star status of a file. + * @async + * @param {string} filename - The name of the file to toggle star for + * @param {string} path - The path of the file + * @throws {Error} If the star toggle operation fails + */ async toggleStar(filename, path) { console.log('[FileManager] Toggling star for:', filename, 'path:', path); const csrfToken = document.querySelector('meta[name="csrf-token"]').getAttribute('content'); @@ -323,6 +383,13 @@ export class FileManager { } } + /** + * Downloads a single file. + * @async + * @param {string} filename - The name of the file to download + * @param {string} [path=''] - The path of the file + * @throws {Error} If the download operation fails + */ async downloadFile(filename, path = '') { console.log('[FileManager] Downloading file:', { filename, path }); const url = `/api/rooms/${this.roomManager.roomId}/files/${encodeURIComponent(filename)}`; @@ -360,6 +427,11 @@ export class FileManager { } } + /** + * Downloads multiple selected files as a zip archive. + * @async + * @throws {Error} If the download operation fails + */ async downloadSelected() { console.log('[FileManager] Downloading selected files...'); const selectedItems = this.getSelectedItems(); @@ -414,6 +486,12 @@ export class FileManager { } } + /** + * Handles the confirmed delete operation after user confirmation. + * Supports both single file and batch deletion. + * @async + * @throws {Error} If the delete operation fails + */ async deleteFileConfirmed() { const csrfToken = document.querySelector('meta[name="csrf-token"]').getAttribute('content'); if (this.batchDeleteItems && this.batchDeleteItems.length) { @@ -476,6 +554,12 @@ export class FileManager { } } + /** + * Updates the file selection based on user interaction. + * Supports single selection, CTRL+click for multiple selection, and SHIFT+click for range selection. + * @param {number} index - The index of the file being selected + * @param {Event} event - The click event that triggered the selection + */ updateSelection(index, event) { console.log('[FileManager] Updating selection:', { index, event }); @@ -521,11 +605,18 @@ export class FileManager { this.roomManager.viewManager.updateMultiSelectUI(); } + /** + * Gets an array of currently selected file objects. + * @returns {Array} Array of selected file objects + */ getSelectedItems() { console.log('[FileManager] Getting selected items'); return Array.from(this.selectedItems).map(index => this.currentFiles[index]); } + /** + * Clears all file selections and updates the UI. + */ clearSelection() { console.log('[FileManager] Clearing selection'); this.selectedItems.clear(); @@ -535,6 +626,9 @@ export class FileManager { this.roomManager.viewManager.updateMultiSelectUI(); } + /** + * Navigates to the parent folder of the current path. + */ navigateToParent() { if (!this.roomManager.currentPath) return; const parts = this.roomManager.currentPath.split('/'); diff --git a/static/js/rooms/modalManager.js b/static/js/rooms/modalManager.js index a01dc2e..fb95cd6 100644 --- a/static/js/rooms/modalManager.js +++ b/static/js/rooms/modalManager.js @@ -1,4 +1,24 @@ +/** + * @fileoverview Manages modal dialogs for the room interface. + * This file handles: + * - Modal initialization and configuration + * - File operations (delete, rename, move) + * - Folder creation + * - File details display + * - Overwrite confirmation + * - Batch operations + */ + +/** + * @class ModalManager + * @classdesc Manages all modal dialogs and their interactions in the room interface. + * Handles file operations, folder creation, and various confirmation dialogs. + */ export class ModalManager { + /** + * Creates a new ModalManager instance. + * @param {RoomManager} roomManager - The parent RoomManager instance + */ constructor(roomManager) { this.roomManager = roomManager; @@ -16,6 +36,10 @@ export class ModalManager { this.initializeModals(); } + /** + * Initializes event listeners for all modals. + * Sets up handlers for delete, new folder, rename, and move operations. + */ initializeModals() { // Initialize delete modal if (this.roomManager.canDelete) { @@ -55,6 +79,11 @@ export class ModalManager { } } + /** + * Shows the delete confirmation modal for a single file. + * @param {string} filename - The name of the file to delete + * @param {string} [path=''] - The path of the file to delete + */ showDeleteModal(filename, path = '') { console.log('[ModalManager] Showing delete modal for:', { filename, path }); const fileNameEl = document.getElementById('deleteFileName'); @@ -82,6 +111,10 @@ export class ModalManager { this.deleteModal.show(); } + /** + * Shows the delete confirmation modal for multiple selected files. + * Processes all selected checkboxes and prepares for batch deletion. + */ showBatchDeleteModal() { const selectedCheckboxes = document.querySelectorAll('.select-item-checkbox:checked'); if (selectedCheckboxes.length === 0) return; @@ -130,6 +163,10 @@ export class ModalManager { this.deleteModal.show(); } + /** + * Shows the rename modal for a file or folder. + * @param {string} filename - The current name of the file/folder + */ showRenameModal(filename) { document.getElementById('renameError').textContent = ''; const ext = filename.includes('.') ? filename.substring(filename.lastIndexOf('.')) : ''; @@ -149,6 +186,10 @@ export class ModalManager { }, 100); } + /** + * Shows the file details modal. + * @param {Object} file - The file object containing details to display + */ showDetailsModal(file) { const icon = file.type === 'folder' ? `` @@ -182,6 +223,11 @@ export class ModalManager { this.detailsModal.show(); } + /** + * Shows the overwrite confirmation modal. + * @param {string} filename - The name of the file that would be overwritten + * @returns {Promise} A promise that resolves with the user's choice ('skip', 'skip_all', 'overwrite', or 'overwrite_all') + */ showOverwriteModal(filename) { return new Promise((resolve) => { const fileNameEl = document.getElementById('overwriteFileName'); @@ -206,6 +252,11 @@ export class ModalManager { }); } + /** + * Shows the move file modal. + * @param {string} fileId - The ID of the file to move + * @param {string} path - The current path of the file + */ showMoveModal(fileId, path) { console.log('[ModalManager] Showing move modal for file:', { fileId, path }); document.getElementById('moveError').textContent = ''; @@ -251,6 +302,10 @@ export class ModalManager { }); } + /** + * Creates a new folder in the current path. + * @async + */ async createFolder() { const folderName = document.getElementById('folderNameInput').value.trim(); if (!folderName) { @@ -290,6 +345,10 @@ export class ModalManager { } } + /** + * Renames a file or folder. + * @async + */ async renameFile() { const newName = document.getElementById('renameInput').value.trim(); if (!newName) { diff --git a/static/js/rooms/room.js b/static/js/rooms/room.js index 6d94432..59e7c8f 100644 --- a/static/js/rooms/room.js +++ b/static/js/rooms/room.js @@ -1,3 +1,13 @@ +/** + * @fileoverview Main room management module that coordinates all room functionality. + * This file handles: + * - Room initialization and configuration + * - Manager coordination (File, View, Upload, Search, Modal) + * - Navigation and path management + * - Event handling and user interactions + * - Permission management + */ + console.log('[RoomManager] Script loaded'); // Main room.js file - Coordinates all room functionality @@ -9,7 +19,23 @@ import { ModalManager } from './modalManager.js'; console.log('[RoomManager] All modules imported successfully'); +/** + * @class RoomManager + * @classdesc Main class that coordinates all room functionality and manages the various + * sub-managers (File, View, Upload, Search, Modal). + */ class RoomManager { + /** + * Creates a new RoomManager instance. + * @param {Object} config - Configuration object for the room + * @param {string} config.roomId - The ID of the room + * @param {boolean} config.canDelete - Whether the user can delete files + * @param {boolean} config.canShare - Whether the user can share files + * @param {boolean} config.canUpload - Whether the user can upload files + * @param {boolean} config.canDownload - Whether the user can download files + * @param {boolean} config.canRename - Whether the user can rename files + * @param {boolean} config.canMove - Whether the user can move files + */ constructor(config) { console.log('[RoomManager] Initializing with config:', config); this.roomId = config.roomId; @@ -33,6 +59,11 @@ class RoomManager { this.initialize(); } + /** + * Initializes the room functionality. + * Sets up the view, fetches files, initializes search, and sets up event listeners. + * @async + */ async initialize() { console.log('[RoomManager] Starting initialization...'); // Get current path from URL @@ -68,12 +99,19 @@ class RoomManager { } } + /** + * Navigates to a subfolder within the current path. + * @param {string} folderName - The name of the folder to navigate to + */ navigateToFolder(folderName) { console.log('[RoomManager] Navigating to folder:', folderName); const newPath = this.currentPath ? `${this.currentPath}/${folderName}` : folderName; this.navigateTo(newPath); } + /** + * Navigates to the parent folder of the current path. + */ navigateToParent() { console.log('[RoomManager] Navigating to parent folder'); if (!this.currentPath) return; @@ -84,6 +122,10 @@ class RoomManager { this.navigateTo(newPath); } + /** + * Navigates to a specific path and updates the URL. + * @param {string} path - The path to navigate to + */ navigateTo(path) { console.log('[RoomManager] Navigating to path:', path); this.currentPath = path; @@ -101,11 +143,20 @@ class RoomManager { }); } + /** + * Gets the current path from the URL parameters. + * @returns {string} The current path from the URL + */ getPathFromUrl() { const urlParams = new URLSearchParams(window.location.search); return urlParams.get('path') || ''; } + /** + * Initializes event listeners for user interactions. + * Sets up handlers for select all, download selected, delete selected, + * and click outside to clear selection. + */ initializeEventListeners() { console.log('[RoomManager] Setting up event listeners'); @@ -151,7 +202,10 @@ class RoomManager { } } -// Initialize the room manager when the DOM is loaded +/** + * Initializes the room manager when the DOM is loaded. + * Creates a new RoomManager instance with configuration from meta tags. + */ document.addEventListener('DOMContentLoaded', () => { const config = { roomId: document.querySelector('meta[name="room-id"]').getAttribute('content'), diff --git a/static/js/rooms/searchManager.js b/static/js/rooms/searchManager.js index 2872f69..2da39b1 100644 --- a/static/js/rooms/searchManager.js +++ b/static/js/rooms/searchManager.js @@ -1,10 +1,34 @@ +/** + * @fileoverview Manages search functionality for the room interface. + * This file handles: + * - Quick search input processing + * - Debounced search execution + * - File filtering based on search terms + * - Search state management + * - Clear search functionality + */ + +/** + * @class SearchManager + * @classdesc Manages search operations including input handling, debounced search execution, + * and file filtering based on search criteria. + */ export class SearchManager { + /** + * Creates a new SearchManager instance. + * @param {RoomManager} roomManager - The parent RoomManager instance + */ constructor(roomManager) { this.roomManager = roomManager; this.searchInput = document.getElementById('quickSearchInput'); this.clearSearchBtn = document.getElementById('clearSearchBtn'); } + /** + * Initializes the search functionality. + * Sets up event listeners for search input and clear button. + * Creates a debounced search function to prevent excessive searches. + */ initialize() { if (!this.searchInput) return; @@ -35,6 +59,11 @@ export class SearchManager { } } + /** + * Performs the search operation on the current file list. + * Filters files based on name and type matching the search term. + * @param {string} searchTerm - The term to search for + */ performSearch(searchTerm) { if (!this.roomManager.fileManager.currentFiles) return; @@ -47,6 +76,14 @@ export class SearchManager { this.roomManager.viewManager.renderFiles(filteredFiles); } + /** + * Creates a debounced version of a function. + * Delays the execution of the function until after a specified wait time + * has elapsed since the last time it was invoked. + * @param {Function} func - The function to debounce + * @param {number} wait - The number of milliseconds to delay + * @returns {Function} The debounced function + */ debounce(func, wait) { let timeout; return function executedFunction(...args) { diff --git a/static/js/rooms/uploadManager.js b/static/js/rooms/uploadManager.js index 6d79db6..4522f93 100644 --- a/static/js/rooms/uploadManager.js +++ b/static/js/rooms/uploadManager.js @@ -1,4 +1,24 @@ +/** + * @fileoverview Manages file upload functionality for the room interface. + * This file handles: + * - File upload initialization and configuration + * - Drag and drop file handling + * - Upload progress tracking + * - File type validation + * - Overwrite handling + * - Batch upload management + */ + +/** + * @class UploadManager + * @classdesc Manages file upload operations including drag-and-drop, progress tracking, + * and handling of file conflicts and validations. + */ export class UploadManager { + /** + * Creates a new UploadManager instance. + * @param {RoomManager} roomManager - The parent RoomManager instance + */ constructor(roomManager) { this.roomManager = roomManager; this.pendingUploads = []; @@ -19,6 +39,10 @@ export class UploadManager { this.initializeUploadHandlers(); } + /** + * Initializes event handlers for file upload functionality. + * Sets up drag and drop handlers and file input change handlers. + */ initializeUploadHandlers() { if (!this.roomManager.canUpload) return; @@ -44,19 +68,33 @@ export class UploadManager { this.fileInput.addEventListener('change', this.handleFileSelect.bind(this)); } + /** + * Prevents default browser behavior for drag and drop events. + * @param {Event} e - The event object + */ preventDefaults(e) { e.preventDefault(); e.stopPropagation(); } + /** + * Highlights the drop zone when files are dragged over it. + */ highlight() { this.dropZoneOverlay.style.display = 'block'; } + /** + * Removes highlight from the drop zone. + */ unhighlight() { this.dropZoneOverlay.style.display = 'none'; } + /** + * Handles files dropped onto the drop zone. + * @param {DragEvent} e - The drop event object + */ async handleDrop(e) { const dt = e.dataTransfer; const files = dt.files; @@ -66,11 +104,18 @@ export class UploadManager { } } + /** + * Handles files selected through the file input. + */ async handleFileSelect() { if (!this.fileInput.files.length) return; await this.startUpload(Array.from(this.fileInput.files)); } + /** + * Initiates the upload process for a set of files. + * @param {Array} files - Array of files to upload + */ async startUpload(files) { this.uploadProgressContainer.style.display = 'block'; this.uploadProgressBar.style.width = '0%'; @@ -85,6 +130,10 @@ export class UploadManager { await this.uploadFilesSequentially(); } + /** + * Uploads files one at a time, handling progress and errors. + * @async + */ async uploadFilesSequentially() { let completedFiles = 0; let currentFileIndex = 0; @@ -182,6 +231,11 @@ export class UploadManager { await processNextFile(); } + /** + * Uploads a single file to the server. + * @param {FormData} formData - Form data containing the file and upload parameters + * @returns {Promise} Response object containing success status and error message if any + */ async uploadFile(formData) { const csrfToken = document.querySelector('meta[name="csrf-token"]').getAttribute('content'); const response = await fetch(`/api/rooms/${this.roomManager.roomId}/files/upload`, { @@ -197,6 +251,11 @@ export class UploadManager { }; } + /** + * Handles file type validation errors. + * Displays error message with allowed file types. + * @param {File} file - The file that failed validation + */ handleFileTypeError(file) { const allowedTypes = [ 'Documents: PDF, DOCX, DOC, TXT, RTF, ODT, MD, CSV', @@ -225,6 +284,12 @@ export class UploadManager { this.uploadProgressBar.className = 'progress-bar bg-danger-opacity-15 text-danger'; } + /** + * Handles file existence conflicts during upload. + * @param {File} file - The file being uploaded + * @param {FormData} formData - Form data for the upload + * @returns {Promise} Object containing continue status + */ async handleFileExists(file, formData) { if (this.overwriteAll) { formData.append('overwrite', 'true'); diff --git a/static/js/rooms/viewManager.js b/static/js/rooms/viewManager.js index b0d8387..5cf8c70 100644 --- a/static/js/rooms/viewManager.js +++ b/static/js/rooms/viewManager.js @@ -1,4 +1,23 @@ +/** + * @fileoverview Manages the file view functionality for the room interface. + * This file handles: + * - Grid and list view rendering + * - File sorting and organization + * - Breadcrumb navigation + * - File action buttons + * - Multi-select functionality + */ + +/** + * @class ViewManager + * @classdesc Manages the visual representation and interaction of files in the room interface. + * Handles view switching, file rendering, sorting, and UI updates. + */ export class ViewManager { + /** + * Creates a new ViewManager instance. + * @param {RoomManager} roomManager - The parent RoomManager instance + */ constructor(roomManager) { console.log('[ViewManager] Initializing...'); this.roomManager = roomManager; @@ -8,6 +27,11 @@ export class ViewManager { console.log('[ViewManager] Initialized with roomManager:', roomManager); } + /** + * Initializes the view with user preferences. + * Fetches and applies the user's preferred view type. + * @async + */ async initializeView() { console.log('[ViewManager] Initializing view...'); try { @@ -29,6 +53,12 @@ export class ViewManager { } } + /** + * Toggles between grid and list views. + * Updates UI and saves user preference. + * @async + * @param {string} view - The view type to switch to ('grid' or 'list') + */ async toggleView(view) { console.log('[ViewManager] Toggling view to:', view); this.currentView = view; @@ -60,6 +90,11 @@ export class ViewManager { } } + /** + * Renders the file list in the current view mode. + * @async + * @param {Array} files - Array of file objects to render + */ async renderFiles(files) { console.log('[ViewManager] Rendering files:', files); const fileGrid = document.getElementById('fileGrid'); @@ -83,6 +118,10 @@ export class ViewManager { } } + /** + * Renders the breadcrumb navigation. + * Shows the current path and provides navigation controls. + */ renderBreadcrumb() { console.log('[ViewManager] Rendering breadcrumb'); const breadcrumb = document.getElementById('breadcrumb'); @@ -140,6 +179,11 @@ export class ViewManager { console.log('[ViewManager] Breadcrumb rendered'); } + /** + * Renders the file list in list view mode. + * @async + * @param {Array} files - Array of file objects to render + */ async renderListView(files) { console.log('[ViewManager] Rendering list view'); const fileGrid = document.getElementById('fileGrid'); @@ -172,6 +216,11 @@ export class ViewManager { console.log('[ViewManager] List view rendered'); } + /** + * Renders the file list in grid view mode. + * @async + * @param {Array} files - Array of file objects to render + */ async renderGridView(files) { console.log('[ViewManager] Rendering grid view'); const fileGrid = document.getElementById('fileGrid'); @@ -193,6 +242,12 @@ export class ViewManager { console.log('[ViewManager] Grid view rendered'); } + /** + * Renders a single file row for list view. + * @param {Object} file - The file object to render + * @param {number} index - The index of the file in the list + * @returns {string} HTML string for the file row + */ renderFileRow(file, index) { console.log('[ViewManager] Rendering file row:', { file, index }); const isFolder = file.type === 'folder'; @@ -226,6 +281,12 @@ export class ViewManager { `; } + /** + * Renders a single file card for grid view. + * @param {Object} file - The file object to render + * @param {number} index - The index of the file in the list + * @returns {string} HTML string for the file card + */ renderFileCard(file, index) { console.log('[ViewManager] Rendering file card:', { file, index }); const isFolder = file.type === 'folder'; @@ -260,6 +321,12 @@ export class ViewManager { `; } + /** + * Renders the action buttons for a file. + * @param {Object} file - The file object + * @param {number} index - The index of the file in the list + * @returns {string} HTML string for the action buttons + */ renderFileActions(file, index) { console.log('[ViewManager] Rendering file actions:', { file, index }); const actions = []; @@ -321,6 +388,11 @@ export class ViewManager { return actions.join(''); } + /** + * Sorts the file list based on current sort settings. + * @param {Array} files - Array of file objects to sort + * @returns {Array} Sorted array of file objects + */ sortFiles(files) { console.log('[ViewManager] Sorting files:', { column: this.sortColumn, @@ -342,6 +414,11 @@ export class ViewManager { }); } + /** + * Gets the appropriate icon class for a file based on its extension. + * @param {string} filename - The name of the file + * @returns {string} Font Awesome icon class name + */ getFileIcon(filename) { const extension = filename.split('.').pop().toLowerCase(); console.log('[ViewManager] Getting icon for file:', { filename, extension }); @@ -368,6 +445,11 @@ export class ViewManager { return iconMap[extension] || 'fa-file'; } + /** + * Formats a file size in bytes to a human-readable string. + * @param {number} bytes - The file size in bytes + * @returns {string} Formatted file size string + */ formatFileSize(bytes) { if (!bytes) return '0 B'; @@ -383,6 +465,9 @@ export class ViewManager { return `${size.toFixed(1)} ${units[unitIndex]}`; } + /** + * Updates the multi-select UI based on current selection state. + */ updateMultiSelectUI() { console.log('[ViewManager] Updating multi-select UI'); const selectedItems = this.roomManager.fileManager.getSelectedItems(); diff --git a/static/js/settings.js b/static/js/settings.js index 61cae45..108f182 100644 --- a/static/js/settings.js +++ b/static/js/settings.js @@ -1,3 +1,13 @@ +/** + * @fileoverview Manages the application settings functionality. + * This file handles color settings, tab persistence, and UI customization. + * It provides functionality to: + * - Manage primary and secondary color schemes + * - Handle settings tab navigation and persistence + * - Convert and manipulate colors (hex, RGB) + * - Update UI elements with new color schemes + */ + document.addEventListener('DOMContentLoaded', function() { const primaryColorInput = document.getElementById('primaryColor'); const secondaryColorInput = document.getElementById('secondaryColor'); @@ -7,7 +17,12 @@ document.addEventListener('DOMContentLoaded', function() { const settingsTabs = document.querySelectorAll('#settingsTabs button[data-bs-toggle="tab"]'); const tabContent = document.querySelectorAll('.tab-pane'); - // Function to activate a specific tab + /** + * Activates a specific settings tab and updates the UI accordingly. + * Also persists the selected tab in localStorage. + * @function + * @param {string} tabId - The ID of the tab to activate + */ function activateTab(tabId) { // Remove active class from all tabs and content settingsTabs.forEach(tab => { @@ -42,7 +57,12 @@ document.addEventListener('DOMContentLoaded', function() { const savedTab = localStorage.getItem('settingsActiveTab') || window.location.hash.substring(1) || 'colors'; activateTab(savedTab); - // Color manipulation functions + /** + * Converts a hexadecimal color code to RGB values. + * @function + * @param {string} hex - The hexadecimal color code (e.g., '#FF0000') + * @returns {Object|null} Object containing r, g, b values or null if invalid hex + */ function hexToRgb(hex) { const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex); return result ? { @@ -52,6 +72,14 @@ document.addEventListener('DOMContentLoaded', function() { } : null; } + /** + * Converts RGB values to a hexadecimal color code. + * @function + * @param {number} r - Red value (0-255) + * @param {number} g - Green value (0-255) + * @param {number} b - Blue value (0-255) + * @returns {string} Hexadecimal color code + */ function rgbToHex(r, g, b) { return '#' + [r, g, b].map(x => { const hex = x.toString(16); @@ -59,6 +87,13 @@ document.addEventListener('DOMContentLoaded', function() { }).join(''); } + /** + * Lightens a color by a specified amount. + * @function + * @param {string} color - The hexadecimal color to lighten + * @param {number} amount - The amount to lighten (0-1) + * @returns {string} The lightened hexadecimal color + */ function lightenColor(color, amount) { const rgb = hexToRgb(color); if (!rgb) return color; @@ -70,6 +105,13 @@ document.addEventListener('DOMContentLoaded', function() { ); } + /** + * Darkens a color by a specified amount. + * @function + * @param {string} color - The hexadecimal color to darken + * @param {number} amount - The amount to darken (0-1) + * @returns {string} The darkened hexadecimal color + */ function darkenColor(color, amount) { const rgb = hexToRgb(color); if (!rgb) return color; @@ -81,6 +123,13 @@ document.addEventListener('DOMContentLoaded', function() { ); } + /** + * Updates all color-related UI elements based on a new color value. + * Updates CSS variables, chart colors, and color previews. + * @function + * @param {string} color - The new color value in hexadecimal + * @param {boolean} isPrimary - Whether this is the primary color (true) or secondary color (false) + */ function updateAllColors(color, isPrimary) { const prefix = isPrimary ? 'primary' : 'secondary'; @@ -162,7 +211,11 @@ document.addEventListener('DOMContentLoaded', function() { updateAllColors(secondaryColorInput.value, false); }); - // Initialize colors from database values + /** + * Initializes the color settings from the current CSS variables. + * Updates input values and color previews. + * @function + */ function initializeColors() { // Get the current computed CSS variable values const computedPrimaryColor = getComputedStyle(document.documentElement).getPropertyValue('--primary-color').trim(); diff --git a/static/js/starred.js b/static/js/starred.js index 1d25adc..7698d27 100644 --- a/static/js/starred.js +++ b/static/js/starred.js @@ -1,10 +1,29 @@ +/** + * @fileoverview Manages the starred files functionality for the document management system. + * This file handles the starred files view and user view preferences. + * It provides functionality to view starred items in either grid or list view + * and manages user view preferences for the starred items section. + */ + let currentView = 'grid'; +/** + * Initializes the starred files view when the DOM content is loaded. + * Sets up the initial view based on user preferences. + * @function + */ document.addEventListener('DOMContentLoaded', function() { // Initialize view initializeView(); }); +/** + * Initializes the view based on user preferences. + * Fetches the user's preferred view (grid or list) and applies it. + * Falls back to grid view if there's an error. + * @async + * @function + */ async function initializeView() { try { const response = await fetch('/api/user/preferred_view'); @@ -18,6 +37,13 @@ async function initializeView() { } } +/** + * Toggles between grid and list views for starred files. + * Updates the UI and saves the user's view preference. + * @function + * @param {string} view - The view to switch to ('grid' or 'list') + * @throws {Error} If the view preference cannot be saved + */ function toggleView(view) { currentView = view; const grid = document.getElementById('fileGrid'); diff --git a/static/js/trash.js b/static/js/trash.js index 28e7287..3492846 100644 --- a/static/js/trash.js +++ b/static/js/trash.js @@ -1,6 +1,18 @@ +/** + * @fileoverview Manages the trash functionality for the document management system. + * This file handles the trash view, empty trash operations, and view preferences. + * It provides functionality to view trashed items in grid or list view, + * empty the trash, and manage user view preferences. + */ + let currentView = 'grid'; -// Make functions globally available +/** + * Shows the empty trash confirmation modal. + * @function + * @global + * @throws {Error} If the modal element is not found or if there's an error showing the modal + */ window.showEmptyTrashModal = function() { console.log('Showing Empty Trash Modal'); const modalEl = document.getElementById('emptyTrashModal'); @@ -20,6 +32,16 @@ window.showEmptyTrashModal = function() { } }; +/** + * Empties the trash by permanently deleting all trashed files. + * This function: + * 1. Fetches all trashed files to get their room IDs + * 2. Makes API calls to empty trash in each room + * 3. Updates the UI to reflect the changes + * @function + * @global + * @throws {Error} If CSRF token is not available or if API calls fail + */ window.emptyTrash = function() { console.log('Emptying Trash'); const csrfToken = document.querySelector('meta[name="csrf-token"]').getAttribute('content'); @@ -85,6 +107,11 @@ window.emptyTrash = function() { }); }; +/** + * Initializes the trash view when the DOM content is loaded. + * Sets up event listeners for empty trash functionality and initializes the view. + * @function + */ document.addEventListener('DOMContentLoaded', function() { console.log('DOM Content Loaded'); @@ -112,6 +139,13 @@ document.addEventListener('DOMContentLoaded', function() { initializeView(); }); +/** + * Initializes the view based on user preferences. + * Fetches the user's preferred view (grid or list) and applies it. + * Falls back to grid view if there's an error. + * @async + * @function + */ async function initializeView() { try { const response = await fetch('/api/user/preferred_view'); @@ -125,6 +159,13 @@ async function initializeView() { } } +/** + * Toggles between grid and list views. + * Updates the UI and saves the user's view preference. + * @function + * @param {string} view - The view to switch to ('grid' or 'list') + * @throws {Error} If the view preference cannot be saved + */ function toggleView(view) { currentView = view; const grid = document.getElementById('fileGrid');