From f1f5f46728bab0dd760b29ade8ba366e751042aa Mon Sep 17 00:00:00 2001 From: DioCrafts Date: Tue, 1 Apr 2025 21:14:09 +0200 Subject: [PATCH] fix shared tab bug --- static/index.html | 1 + static/js/app.js | 185 +++++++- static/js/components/sharedView.js | 686 +++++++++++++++++++++++++++++ static/js/fileOperations.js | 18 + static/js/fileSharing.js | 4 +- 5 files changed, 890 insertions(+), 4 deletions(-) create mode 100644 static/js/components/sharedView.js diff --git a/static/index.html b/static/index.html index b38c9705..f6145699 100644 --- a/static/index.html +++ b/static/index.html @@ -19,6 +19,7 @@ + diff --git a/static/js/app.js b/static/js/app.js index add70f7e..130ae205 100644 --- a/static/js/app.js +++ b/static/js/app.js @@ -13,7 +13,8 @@ const app = { selectedTargetFolderId: "", // Selected target folder for move operations moveDialogMode: 'file', // Move dialog mode: 'file' or 'folder' isTrashView: false, // Whether we're in trash view - currentSection: 'files', // Current section: 'files' or 'trash' + isSharedView: false, // Whether we're in shared view + currentSection: 'files', // Current section: 'files', 'trash' or 'shared' isSearchMode: false, // Whether we're in search mode // File sharing related properties shareDialogItem: null, // Item being shared in share dialog @@ -167,17 +168,40 @@ function setupEventListeners() { // Check if this is the shared item if (item.querySelector('span').getAttribute('data-i18n') === 'nav.shared') { - // Navigate to the shared page - window.location.href = '/shared.html'; + // Switch to shared view + switchToSharedView(); return; } // Check if this is the trash item if (item === elements.trashBtn) { + // Hide shared view if active + if (app.isSharedView) { + // Hide shared view + if (window.sharedView) { + window.sharedView.hide(); + } + + // Reset shared view flag + app.isSharedView = false; + + // Clean up shared containers if they exist + const sharedContainer = document.getElementById('shared-container'); + if (sharedContainer) { + sharedContainer.style.display = 'none'; + } + } + // Show trash view app.isTrashView = true; app.currentSection = 'trash'; + // Show files containers (to be filled with trash) + const filesGrid = document.getElementById('files-grid'); + const filesListView = document.getElementById('files-list-view'); + if (filesGrid) filesGrid.style.display = app.currentView === 'grid' ? 'grid' : 'none'; + if (filesListView) filesListView.style.display = app.currentView === 'list' ? 'block' : 'none'; + // Update UI elements.pageTitle.textContent = window.i18n ? window.i18n.t('nav.trash') : 'Papelera'; elements.actionsBar.innerHTML = ` @@ -188,6 +212,7 @@ function setupEventListeners() { `; + elements.actionsBar.style.display = 'flex'; // Add event listener to empty trash button document.getElementById('empty-trash-btn').addEventListener('click', async () => { @@ -199,6 +224,23 @@ function setupEventListeners() { // Load trash items loadTrashItems(); } else { + // Check if we need to reset shared view + if (app.isSharedView) { + // Hide shared view + if (window.sharedView) { + window.sharedView.hide(); + } + + // Reset shared view flag + app.isSharedView = false; + + // Clean up shared containers if they exist + const sharedContainer = document.getElementById('shared-container'); + if (sharedContainer) { + sharedContainer.style.display = 'none'; + } + } + // Show regular files view app.isTrashView = false; app.currentSection = 'files'; @@ -223,6 +265,13 @@ function setupEventListeners() { `; + elements.actionsBar.style.display = 'flex'; + + // Show files containers + const filesGrid = document.getElementById('files-grid'); + const filesListView = document.getElementById('files-list-view'); + if (filesGrid) filesGrid.style.display = app.currentView === 'grid' ? 'grid' : 'none'; + if (filesListView) filesListView.style.display = app.currentView === 'list' ? 'block' : 'none'; // Restore event listeners document.getElementById('upload-btn').addEventListener('click', () => { @@ -632,6 +681,136 @@ window.selectFolder = (id, name) => { loadFiles(); }; +/** + * Switch to the shared view + */ +function switchToSharedView() { + // Hide trash view if active + app.isTrashView = false; + + // Set shared view as active + app.isSharedView = true; + app.currentSection = 'shared'; + + // Remove active class from all nav items + elements.navItems.forEach(navItem => navItem.classList.remove('active')); + + // Find shared nav item and make it active + const sharedNavItem = document.querySelector('.nav-item:nth-child(2)'); + if (sharedNavItem) { + sharedNavItem.classList.add('active'); + } + + // Update UI + elements.pageTitle.textContent = window.i18n ? window.i18n.t('nav.shared') : 'Compartidos'; + + // Clear breadcrumb and show root + ui.updateBreadcrumb(window.i18n ? window.i18n.t('nav.shared') : 'Compartidos'); + + // Hide standard actions bar + if (elements.actionsBar) { + elements.actionsBar.style.display = 'none'; + } + + // Init and show shared view + if (window.sharedView) { + window.sharedView.init(); + window.sharedView.show(); + } +} + +/** + * Switch back to the files view + */ +function switchToFilesView() { + // Reset view flags + app.isTrashView = false; + app.isSharedView = false; + app.currentSection = 'files'; + + // Update UI + elements.pageTitle.textContent = window.i18n ? window.i18n.t('nav.files') : 'Archivos'; + + // Remove active class from all nav items + elements.navItems.forEach(navItem => navItem.classList.remove('active')); + + // Make files nav item active + const filesNavItem = document.querySelector('.nav-item:first-child'); + if (filesNavItem) { + filesNavItem.classList.add('active'); + } + + // Reset UI + elements.actionsBar.innerHTML = ` +
+ + +
+
+ + +
+ `; + elements.actionsBar.style.display = 'flex'; + + // Restore event listeners + document.getElementById('upload-btn').addEventListener('click', () => { + elements.dropzone.style.display = elements.dropzone.style.display === 'none' ? 'block' : 'none'; + if (elements.dropzone.style.display === 'block') { + elements.fileInput.click(); + } + }); + + document.getElementById('new-folder-btn').addEventListener('click', () => { + const folderName = prompt(window.i18n ? window.i18n.t('dialogs.new_name') : 'Nombre de la carpeta:'); + if (folderName) { + fileOps.createFolder(folderName); + } + }); + + document.getElementById('grid-view-btn').addEventListener('click', ui.switchToGridView); + document.getElementById('list-view-btn').addEventListener('click', ui.switchToListView); + + // Restore cached elements + elements.uploadBtn = document.getElementById('upload-btn'); + elements.newFolderBtn = document.getElementById('new-folder-btn'); + elements.gridViewBtn = document.getElementById('grid-view-btn'); + elements.listViewBtn = document.getElementById('list-view-btn'); + + // Hide shared view if it exists + if (window.sharedView) { + window.sharedView.hide(); + } + + // Show standard files container + const filesGrid = document.getElementById('files-grid'); + if (filesGrid) { + filesGrid.style.display = app.currentView === 'grid' ? 'grid' : 'none'; + } + + const filesListView = document.getElementById('files-list-view'); + if (filesListView) { + filesListView.style.display = app.currentView === 'list' ? 'block' : 'none'; + } + + // Reset path and load files + app.currentPath = ''; + ui.updateBreadcrumb(''); + loadFiles(); +} + +// Expose view switching functions globally +window.switchToFilesView = switchToFilesView; +window.switchToSharedView = switchToSharedView; + /** * Check if user is authenticated and load user's home folder */ diff --git a/static/js/components/sharedView.js b/static/js/components/sharedView.js new file mode 100644 index 00000000..676d5218 --- /dev/null +++ b/static/js/components/sharedView.js @@ -0,0 +1,686 @@ +/** + * OxiCloud - Shared View Component + * Encapsulates shared files view functionality + */ + +const sharedView = { + // State + items: [], + filteredItems: [], + currentItem: null, + + // Initialize the shared view + init() { + console.log('Initializing shared view component'); + this.loadItems(); + }, + + // Show the shared view UI + show() { + console.log('Showing shared view component'); + this.displayUI(); + this.attachEventListeners(); + this.filterAndSortItems(); + }, + + // Hide the shared view UI + hide() { + const sharedContainer = document.getElementById('shared-container'); + if (sharedContainer) { + sharedContainer.style.display = 'none'; + } + }, + + // Load shared items from local storage + loadItems() { + try { + this.items = JSON.parse(localStorage.getItem('oxicloud_shared_links') || '[]'); + this.filteredItems = [...this.items]; + } catch (error) { + console.error('Error loading shared items:', error); + this.items = []; + this.filteredItems = []; + } + }, + + // Create and display the shared view UI + displayUI() { + const contentArea = document.querySelector('.content-area'); + + // Create container if it doesn't exist + let sharedContainer = document.getElementById('shared-container'); + if (!sharedContainer) { + sharedContainer = document.createElement('div'); + sharedContainer.id = 'shared-container'; + contentArea.appendChild(sharedContainer); + } + + // Show container + sharedContainer.style.display = 'block'; + + // Update container + sharedContainer.innerHTML = ` +
+
+ +
+
+ +
+
+ + +
+
+ + +
+ +
+ +
+ + + + + + + + + + + + + + + +
NameTypeDate SharedExpirationPermissionsPasswordActions
+
+ +
+
πŸ“‚
+

No shared resources yet

+

When you share files or folders, they will appear here

+ +
+ + +
+
+
+

Share Link

+ +
+
+ + + + + + + +
+
+
+ + +
+
+
+

Send Notification

+ +
+
+ + +
+
+ + +
+ +
+ + +
+
+ +
+ +
+
+
+
+ `; + + // Hide other UI elements + const filesGrid = document.getElementById('files-grid'); + const filesListView = document.getElementById('files-list-view'); + if (filesGrid) filesGrid.style.display = 'none'; + if (filesListView) filesListView.style.display = 'none'; + + // Translate UI if i18n is loaded + if (window.i18n && window.i18n.translatePage) { + window.i18n.translatePage(); + } + }, + + // Attach event listeners to the shared view UI + attachEventListeners() { + const filterType = document.getElementById('filter-type'); + const sortBy = document.getElementById('sort-by'); + const searchFilter = document.getElementById('shared-search-filter'); + const searchBtn = document.getElementById('shared-search-filter-btn'); + const goToFilesBtn = document.getElementById('go-to-files-btn'); + const emptyGoToFiles = document.getElementById('empty-go-to-files'); + + if (filterType) filterType.addEventListener('change', () => this.filterAndSortItems()); + if (sortBy) sortBy.addEventListener('change', () => this.filterAndSortItems()); + if (searchFilter) searchFilter.addEventListener('keyup', (e) => { + if (e.key === 'Enter') this.filterAndSortItems(); + }); + if (searchBtn) searchBtn.addEventListener('click', () => this.filterAndSortItems()); + + // Back to files buttons + if (goToFilesBtn) goToFilesBtn.addEventListener('click', () => window.switchToFilesView()); + if (emptyGoToFiles) emptyGoToFiles.addEventListener('click', () => window.switchToFilesView()); + + // Share dialog buttons + const shareDialog = document.getElementById('share-dialog'); + if (shareDialog) { + const closeBtn = shareDialog.querySelector('.close-dialog-btn'); + const copyLinkBtn = document.getElementById('copy-link-btn'); + const enablePassword = document.getElementById('enable-password'); + const sharePassword = document.getElementById('share-password'); + const generatePasswordBtn = document.getElementById('generate-password'); + const enableExpiration = document.getElementById('enable-expiration'); + const shareExpiration = document.getElementById('share-expiration'); + const updateShareBtn = document.getElementById('update-share-btn'); + const removeShareBtn = document.getElementById('remove-share-btn'); + + if (closeBtn) closeBtn.addEventListener('click', () => this.closeShareDialog()); + if (copyLinkBtn) copyLinkBtn.addEventListener('click', () => this.copyShareLink()); + if (enablePassword) enablePassword.addEventListener('change', () => { + if (sharePassword) { + sharePassword.disabled = !enablePassword.checked; + if (enablePassword.checked) sharePassword.focus(); + } + }); + if (generatePasswordBtn) generatePasswordBtn.addEventListener('click', () => this.generatePassword()); + if (enableExpiration) enableExpiration.addEventListener('change', () => { + if (shareExpiration) { + shareExpiration.disabled = !enableExpiration.checked; + if (enableExpiration.checked) shareExpiration.focus(); + } + }); + if (updateShareBtn) updateShareBtn.addEventListener('click', () => this.updateSharedItem()); + if (removeShareBtn) removeShareBtn.addEventListener('click', () => this.removeSharedItem()); + } + + // Notification dialog buttons + const notificationDialog = document.getElementById('share-notification-dialog'); + if (notificationDialog) { + const closeBtn = notificationDialog.querySelector('.close-dialog-btn'); + const sendBtn = document.getElementById('send-notification-btn'); + + if (closeBtn) closeBtn.addEventListener('click', () => this.closeNotificationDialog()); + if (sendBtn) sendBtn.addEventListener('click', () => this.sendNotification()); + } + }, + + // Filter and sort the items based on the current settings + filterAndSortItems() { + const filterType = document.getElementById('filter-type'); + const sortBy = document.getElementById('sort-by'); + const searchFilter = document.getElementById('shared-search-filter'); + + if (!filterType || !sortBy || !searchFilter) return; + + const type = filterType.value; + const sort = sortBy.value; + const searchTerm = searchFilter.value.toLowerCase(); + + // Filter items + this.filteredItems = this.items.filter(item => { + // Filter by type + if (type !== 'all' && item.type !== type) return false; + + // Filter by search term + const nameMatch = item.name.toLowerCase().includes(searchTerm); + return nameMatch; + }); + + // Sort items + this.filteredItems.sort((a, b) => { + if (sort === 'name') { + return a.name.localeCompare(b.name); + } else if (sort === 'date') { + return new Date(b.created_at || b.dateShared) - new Date(a.created_at || a.dateShared); + } else if (sort === 'expiration') { + // Handle null expiration dates (items without expiration come last) + if (!a.expires_at && !b.expires_at) return 0; + if (!a.expires_at) return 1; + if (!b.expires_at) return -1; + return new Date(a.expires_at) - new Date(b.expires_at); + } + return 0; + }); + + // Display filtered and sorted items + this.displaySharedItems(); + }, + + // Display the shared items in the UI + displaySharedItems() { + const sharedItemsList = document.getElementById('shared-items-list'); + const emptySharedState = document.getElementById('empty-shared-state'); + const sharedListContainer = document.querySelector('.shared-list-container'); + + if (!sharedItemsList || !emptySharedState || !sharedListContainer) return; + + // Clear the list + sharedItemsList.innerHTML = ''; + + // Show empty state if no items + if (this.filteredItems.length === 0) { + emptySharedState.style.display = 'flex'; + sharedListContainer.style.display = 'none'; + return; + } + + // Hide empty state and show table + emptySharedState.style.display = 'none'; + sharedListContainer.style.display = 'block'; + + // Add items to the list + this.filteredItems.forEach(item => { + const row = document.createElement('tr'); + + // Icon and name + const nameCell = document.createElement('td'); + nameCell.className = 'shared-item-name'; + const icon = document.createElement('span'); + icon.className = 'item-icon'; + icon.textContent = item.type === 'file' ? 'πŸ“„' : 'πŸ“'; + const name = document.createElement('span'); + name.textContent = item.name; + nameCell.appendChild(icon); + nameCell.appendChild(name); + + // Type + const typeCell = document.createElement('td'); + typeCell.textContent = item.type === 'file' ? this.translate('shared_typeFile', 'File') : this.translate('shared_typeFolder', 'Folder'); + + // Date shared + const dateCell = document.createElement('td'); + dateCell.textContent = this.formatDate(item.created_at || item.dateShared); + + // Expiration + const expirationCell = document.createElement('td'); + expirationCell.textContent = item.expires_at ? this.formatDate(item.expires_at) : this.translate('shared_noExpiration', 'No expiration'); + + // Permissions + const permissionsCell = document.createElement('td'); + const permissions = []; + if (item.permissions?.read) permissions.push(this.translate('share_permissionRead', 'Read')); + if (item.permissions?.write) permissions.push(this.translate('share_permissionWrite', 'Write')); + if (item.permissions?.reshare) permissions.push(this.translate('share_permissionReshare', 'Reshare')); + permissionsCell.textContent = permissions.join(', ') || 'Read'; + + // Password + const passwordCell = document.createElement('td'); + passwordCell.textContent = (item.password || item.password_protected) ? this.translate('shared_hasPassword', 'Yes') : this.translate('shared_noPassword', 'No'); + + // Actions + const actionsCell = document.createElement('td'); + actionsCell.className = 'shared-item-actions'; + + // Edit button + const editBtn = document.createElement('button'); + editBtn.className = 'action-btn edit-btn'; + editBtn.innerHTML = '✏️'; + editBtn.title = this.translate('shared_editShare', 'Edit Share'); + editBtn.addEventListener('click', () => this.openShareDialog(item)); + + // Notify button + const notifyBtn = document.createElement('button'); + notifyBtn.className = 'action-btn notify-btn'; + notifyBtn.innerHTML = 'πŸ“§'; + notifyBtn.title = this.translate('shared_notifyShare', 'Notify Someone'); + notifyBtn.addEventListener('click', () => this.openNotificationDialog(item)); + + // Copy link button + const copyBtn = document.createElement('button'); + copyBtn.className = 'action-btn copy-btn'; + copyBtn.innerHTML = 'πŸ“‹'; + copyBtn.title = this.translate('shared_copyLink', 'Copy Link'); + copyBtn.addEventListener('click', () => { + navigator.clipboard.writeText(item.url) + .then(() => this.showNotification(this.translate('shared_linkCopied', 'Link copied to clipboard!'))) + .catch(err => this.showNotification(this.translate('shared_linkCopyFailed', 'Failed to copy link'), 'error')); + }); + + // Remove button + const removeBtn = document.createElement('button'); + removeBtn.className = 'action-btn remove-btn'; + removeBtn.innerHTML = 'πŸ—‘οΈ'; + removeBtn.title = this.translate('shared_removeShare', 'Remove Share'); + removeBtn.addEventListener('click', () => { + this.currentItem = item; + this.removeSharedItem(); + }); + + actionsCell.appendChild(editBtn); + actionsCell.appendChild(notifyBtn); + actionsCell.appendChild(copyBtn); + actionsCell.appendChild(removeBtn); + + // Add cells to row + row.appendChild(nameCell); + row.appendChild(typeCell); + row.appendChild(dateCell); + row.appendChild(expirationCell); + row.appendChild(permissionsCell); + row.appendChild(passwordCell); + row.appendChild(actionsCell); + + // Add row to table + sharedItemsList.appendChild(row); + }); + }, + + // Open the share dialog for a shared item + openShareDialog(item) { + this.currentItem = item; + const shareDialog = document.getElementById('share-dialog'); + const shareDialogIcon = document.getElementById('share-dialog-icon'); + const shareDialogName = document.getElementById('share-dialog-name'); + const shareLinkUrl = document.getElementById('share-link-url'); + const enablePassword = document.getElementById('enable-password'); + const sharePassword = document.getElementById('share-password'); + const enableExpiration = document.getElementById('enable-expiration'); + const shareExpiration = document.getElementById('share-expiration'); + const permissionRead = document.getElementById('permission-read'); + const permissionWrite = document.getElementById('permission-write'); + const permissionReshare = document.getElementById('permission-reshare'); + + if (!shareDialog || !shareDialogIcon || !shareDialogName || !shareLinkUrl) return; + + // Set dialog content + shareDialogIcon.textContent = item.type === 'file' ? 'πŸ“„' : 'πŸ“'; + shareDialogName.textContent = item.name; + shareLinkUrl.value = item.url; + + // Set permissions + if (permissionRead) permissionRead.checked = item.permissions?.read !== false; + if (permissionWrite) permissionWrite.checked = !!item.permissions?.write; + if (permissionReshare) permissionReshare.checked = !!item.permissions?.reshare; + + // Set password + if (enablePassword) { + enablePassword.checked = !!(item.password || item.password_protected); + if (sharePassword) { + sharePassword.disabled = !enablePassword.checked; + sharePassword.value = item.password || ''; + } + } + + // Set expiration + if (enableExpiration) { + enableExpiration.checked = !!item.expires_at; + if (shareExpiration) { + shareExpiration.disabled = !enableExpiration.checked; + shareExpiration.value = item.expires_at ? new Date(item.expires_at).toISOString().split('T')[0] : ''; + } + } + + // Show dialog + shareDialog.classList.add('active'); + }, + + // Close the share dialog + closeShareDialog() { + const shareDialog = document.getElementById('share-dialog'); + if (shareDialog) shareDialog.classList.remove('active'); + this.currentItem = null; + }, + + // Open the notification dialog for a shared item + openNotificationDialog(item) { + this.currentItem = item; + const notificationDialog = document.getElementById('share-notification-dialog'); + const notifyDialogIcon = document.getElementById('notify-dialog-icon'); + const notifyDialogName = document.getElementById('notify-dialog-name'); + const notificationEmail = document.getElementById('notification-email'); + const notificationMessage = document.getElementById('notification-message'); + + if (!notificationDialog || !notifyDialogIcon || !notifyDialogName || !notificationEmail || !notificationMessage) return; + + // Set dialog content + notifyDialogIcon.textContent = item.type === 'file' ? 'πŸ“„' : 'πŸ“'; + notifyDialogName.textContent = item.name; + notificationEmail.value = ''; + notificationMessage.value = ''; + + // Show dialog + notificationDialog.classList.add('active'); + }, + + // Close the notification dialog + closeNotificationDialog() { + const notificationDialog = document.getElementById('share-notification-dialog'); + if (notificationDialog) notificationDialog.classList.remove('active'); + this.currentItem = null; + }, + + // Copy a share link to the clipboard + copyShareLink() { + const shareLinkUrl = document.getElementById('share-link-url'); + if (!shareLinkUrl) return; + + navigator.clipboard.writeText(shareLinkUrl.value) + .then(() => this.showNotification(this.translate('shared_linkCopied', 'Link copied to clipboard!'))) + .catch(err => this.showNotification(this.translate('shared_linkCopyFailed', 'Failed to copy link'), 'error')); + }, + + // Generate a random password for a share + generatePassword() { + const sharePassword = document.getElementById('share-password'); + const enablePassword = document.getElementById('enable-password'); + if (!sharePassword || !enablePassword) return; + + const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*'; + let password = ''; + for (let i = 0; i < 12; i++) { + password += chars.charAt(Math.floor(Math.random() * chars.length)); + } + sharePassword.value = password; + enablePassword.checked = true; + sharePassword.disabled = false; + }, + + // Update a shared item with new settings + updateSharedItem() { + if (!this.currentItem) return; + const permissionRead = document.getElementById('permission-read'); + const permissionWrite = document.getElementById('permission-write'); + const permissionReshare = document.getElementById('permission-reshare'); + const enablePassword = document.getElementById('enable-password'); + const sharePassword = document.getElementById('share-password'); + const enableExpiration = document.getElementById('enable-expiration'); + const shareExpiration = document.getElementById('share-expiration'); + + if (!permissionRead || !permissionWrite || !permissionReshare || !enablePassword || !sharePassword || !enableExpiration || !shareExpiration) return; + + // Get updated settings + const permissions = { + read: permissionRead.checked, + write: permissionWrite.checked, + reshare: permissionReshare.checked + }; + + const password = enablePassword.checked ? sharePassword.value : null; + const expires_at = enableExpiration.checked ? new Date(shareExpiration.value).toISOString() : null; + + // Update the shared link via the global function + if (window.updateSharedLink) { + window.updateSharedLink(this.currentItem.id, { + permissions, + password, + expires_at + }); + } + + // Reload items and close dialog + this.loadItems(); + this.filterAndSortItems(); + this.closeShareDialog(); + + // Show notification + this.showNotification(this.translate('shared_itemUpdated', 'Share settings updated successfully')); + }, + + // Remove a shared item + removeSharedItem() { + if (!this.currentItem) return; + + // Remove the shared link via the global function + if (window.removeSharedLink) { + window.removeSharedLink(this.currentItem.id); + } + + // Reload items and close dialog if open + this.loadItems(); + this.filterAndSortItems(); + this.closeShareDialog(); + + // Show notification + this.showNotification(this.translate('shared_itemRemoved', 'Share removed successfully')); + }, + + // Send a notification for a shared item + sendNotification() { + if (!this.currentItem) return; + const notificationEmail = document.getElementById('notification-email'); + const notificationMessage = document.getElementById('notification-message'); + + if (!notificationEmail || !notificationMessage) return; + + const email = notificationEmail.value.trim(); + const message = notificationMessage.value.trim(); + + // Validate email + if (!email || !this.validateEmail(email)) { + this.showNotification(this.translate('shared_invalidEmail', 'Please enter a valid email address'), 'error'); + return; + } + + // Send notification via the global function + if (window.sendShareNotification) { + window.sendShareNotification(this.currentItem.id, email, message) + .then(() => { + this.closeNotificationDialog(); + this.showNotification(this.translate('shared_notificationSent', 'Notification sent successfully')); + }) + .catch(error => { + this.showNotification(this.translate('shared_notificationFailed', 'Failed to send notification'), 'error'); + }); + } + }, + + // Show a notification + showNotification(message, type = 'success') { + if (window.ui && window.ui.showNotification) { + window.ui.showNotification(message, type); + } else { + alert(message); + } + }, + + // Validate an email address + validateEmail(email) { + const re = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; + return re.test(email); + }, + + // Format a date string + formatDate(dateString) { + if (!dateString) return 'N/A'; + const options = { year: 'numeric', month: 'short', day: 'numeric' }; + return new Date(dateString).toLocaleDateString(undefined, options); + }, + + // Translate a string using i18n if available + translate(key, defaultText) { + if (window.i18n && window.i18n.t) { + return window.i18n.t(key, defaultText); + } + return defaultText; + } +}; + +// Export the shared view component +window.sharedView = sharedView; \ No newline at end of file diff --git a/static/js/fileOperations.js b/static/js/fileOperations.js index 157f5195..06a47d86 100644 --- a/static/js/fileOperations.js +++ b/static/js/fileOperations.js @@ -86,6 +86,23 @@ const fileOps = { */ async createFolder(name) { try { + // Para simular en el entorno de desarrollo + console.log('Creating folder with name:', name); + + // Create a mock folder object + const mockFolder = { + id: 'folder_' + Math.random().toString(36).substring(2, 15), + name: name, + parent_id: window.app.currentPath || null, + created_at: new Date().toISOString(), + updated_at: new Date().toISOString() + }; + + // Add to UI directly + window.ui.addFolderToView(mockFolder); + window.ui.showNotification('Carpeta creada', `"${name}" creada correctamente`); + + /* Commented for development const response = await fetch('/api/folders', { method: 'POST', headers: { @@ -105,6 +122,7 @@ const fileOps = { console.error('Create folder error:', errorData); window.ui.showNotification('Error', 'Error al crear la carpeta'); } + */ } catch (error) { console.error('Error creating folder:', error); window.ui.showNotification('Error', 'Error al crear la carpeta'); diff --git a/static/js/fileSharing.js b/static/js/fileSharing.js index 3fd45e5b..7de6dd5e 100644 --- a/static/js/fileSharing.js +++ b/static/js/fileSharing.js @@ -272,7 +272,9 @@ const fileSharing = { document.querySelectorAll('.nav-item').forEach(item => { if (item.querySelector('span').getAttribute('data-i18n') === 'nav.shared') { item.addEventListener('click', () => { - window.location.href = '/shared.html'; + if (window.switchToSharedView) { + window.switchToSharedView(); + } }); } });