2025-03-19 23:28:29 +01:00
/**
* OxiCloud - File Operations Module
* This file handles file and folder operations (create, move, delete, rename, upload)
*/
2026-02-08 22:44:42 +01:00
/**
* Get authorization headers for API requests
* @returns {Object} Headers object with Authorization bearer token
*/
function getAuthHeaders () {
const token = localStorage . getItem ( 'oxicloud_token' );
const headers = {};
if ( token ) {
headers [ 'Authorization' ] = `Bearer ${ token } ` ;
}
return headers ;
}
2025-03-19 23:28:29 +01:00
// File Operations Module
const fileOps = {
/**
* Upload files to the server
* @param {FileList} files - Files to upload
*/
async uploadFiles ( files ) {
const progressBar = document . querySelector ( '.progress-fill' );
const uploadProgressDiv = document . querySelector ( '.upload-progress' );
uploadProgressDiv . style . display = 'block' ;
progressBar . style . width = '0%' ;
let uploadedCount = 0 ;
const totalFiles = files . length ;
for ( let i = 0 ; i < totalFiles ; i ++ ) {
const file = files [ i ];
const formData = new FormData ();
2026-02-03 17:59:04 +01:00
// IMPORTANT: folder_id MUST be added BEFORE file for multipart processing
// The backend reads fields in order, and needs folder_id before processing the file
const targetFolderId = window . app . currentPath || window . app . userHomeFolderId ;
if ( targetFolderId ) {
formData . append ( 'folder_id' , targetFolderId );
2025-03-19 23:28:29 +01:00
}
2026-02-03 17:59:04 +01:00
// Add the file AFTER folder_id
formData . append ( 'file' , file );
2025-03-19 23:28:29 +01:00
try {
2026-02-03 17:59:04 +01:00
console . log ( `Uploading file to folder: ${ targetFolderId || 'root' } ` );
2025-03-23 22:44:18 +01:00
2026-02-12 09:41:25 +01:00
// We use the correct URL for file upload
console . log ( 'Form to submit:' , {
2025-03-23 22:44:18 +01:00
file : file . name ,
size : file . size ,
2026-02-03 17:59:04 +01:00
folder_id : targetFolderId || 'root'
2025-03-23 22:44:18 +01:00
});
2025-03-19 23:28:29 +01:00
const response = await fetch ( '/api/files/upload' , {
method : 'POST' ,
2025-04-12 12:21:57 +02:00
body : formData ,
2026-02-12 09:41:25 +01:00
// Add cache: 'no-store' to avoid cache issues during upload
2025-04-12 12:21:57 +02:00
cache : 'no-store' ,
headers : {
2026-02-08 22:44:42 +01:00
... getAuthHeaders (),
2026-02-12 09:41:25 +01:00
// Add this header to force fresh reloads
2025-04-12 12:21:57 +02:00
'Cache-Control' : 'no-cache, no-store, must-revalidate'
}
2025-03-19 23:28:29 +01:00
});
2025-03-23 22:44:18 +01:00
2026-02-12 09:41:25 +01:00
console . log ( 'Server response:' , {
2025-03-23 22:44:18 +01:00
status : response . status ,
statusText : response . statusText
});
2025-03-19 23:28:29 +01:00
// Update progress
uploadedCount ++ ;
const percentComplete = ( uploadedCount / totalFiles ) * 100 ;
progressBar . style . width = percentComplete + '%' ;
if ( response . ok ) {
2025-03-23 22:44:18 +01:00
const responseData = await response . json ();
console . log ( `Successfully uploaded ${ file . name } ` , responseData );
2025-04-12 12:21:57 +02:00
2026-02-03 17:59:04 +01:00
// Show success notification immediately
2026-02-12 09:41:25 +01:00
window . ui . showNotification ( 'File uploaded' , ` ${ file . name } completed` );
2025-03-19 23:28:29 +01:00
if ( i === totalFiles - 1 ) {
2026-02-03 17:59:04 +01:00
// Last file uploaded - wait and reload once
2026-02-12 09:41:25 +01:00
console . log ( 'Last file uploaded, waiting before reloading...' );
2025-04-12 12:21:57 +02:00
2026-02-03 17:59:04 +01:00
// Wait for backend to persist
await new Promise ( resolve => setTimeout ( resolve , 800 ));
// Single reload with force refresh
2025-04-12 12:21:57 +02:00
try {
await window . loadFiles ({ forceRefresh : true });
} catch ( reloadError ) {
2026-02-12 09:41:25 +01:00
console . error ( "Error reloading files:" , reloadError );
2025-04-12 12:21:57 +02:00
}
2026-02-03 17:59:04 +01:00
// Hide upload UI
2025-03-19 23:28:29 +01:00
setTimeout (() => {
2026-02-03 17:59:04 +01:00
const dropzone = document . getElementById ( 'dropzone' );
if ( dropzone ) dropzone . style . display = 'none' ;
2025-03-19 23:28:29 +01:00
uploadProgressDiv . style . display = 'none' ;
2026-02-03 17:59:04 +01:00
}, 500 );
2025-03-19 23:28:29 +01:00
}
} else {
const errorData = await response . text ();
console . error ( 'Upload error:' , errorData );
2026-02-12 09:41:25 +01:00
window . ui . showNotification ( 'Error' , `Error uploading file: ${ file . name } ` );
2025-03-19 23:28:29 +01:00
}
} catch ( error ) {
console . error ( 'Network error during upload:' , error );
2026-02-12 09:41:25 +01:00
window . ui . showNotification ( 'Error' , `Network error uploading file: ${ file . name } ` );
2025-03-19 23:28:29 +01:00
}
}
},
2026-02-08 22:44:42 +01:00
/**
* Upload folder files maintaining directory structure
* Creates subfolders as needed, then uploads files into them
* @param {FileList} files - Files from folder input (with webkitRelativePath)
*/
async uploadFolderFiles ( files ) {
if ( ! files || files . length === 0 ) return ;
const progressBar = document . querySelector ( '.progress-fill' );
const uploadProgressDiv = document . querySelector ( '.upload-progress' );
uploadProgressDiv . style . display = 'block' ;
progressBar . style . width = '0%' ;
const currentFolderId = window . app . currentPath || window . app . userHomeFolderId ;
// Build folder structure from relative paths
// webkitRelativePath looks like: "folderName/subfolder/file.txt"
const folderMap = new Map (); // path -> folder_id
folderMap . set ( '' , currentFolderId ); // root = current folder
// Collect all unique folder paths
const folderPaths = new Set ();
for ( const file of files ) {
const parts = file . webkitRelativePath . split ( '/' );
// Remove filename, keep folder parts
for ( let i = 1 ; i < parts . length ; i ++ ) {
const path = parts . slice ( 0 , i ). join ( '/' );
folderPaths . add ( path );
}
}
// Sort paths by depth so parents are created first
const sortedPaths = [... folderPaths ]. sort (( a , b ) =>
a . split ( '/' ). length - b . split ( '/' ). length
);
// Create folders
for ( const folderPath of sortedPaths ) {
const parts = folderPath . split ( '/' );
const folderName = parts [ parts . length - 1 ];
const parentPath = parts . slice ( 0 , - 1 ). join ( '/' );
const parentId = folderMap . get ( parentPath ) || currentFolderId ;
try {
const response = await fetch ( '/api/folders' , {
method : 'POST' ,
headers : {
... getAuthHeaders (),
'Content-Type' : 'application/json' ,
'Cache-Control' : 'no-cache, no-store, must-revalidate'
},
body : JSON . stringify ({
name : folderName ,
parent_id : parentId
})
});
if ( response . ok ) {
const folder = await response . json ();
folderMap . set ( folderPath , folder . id );
console . log ( `Created folder: ${ folderPath } -> ${ folder . id } ` );
} else {
console . error ( `Error creating folder ${ folderPath } :` , await response . text ());
2026-02-12 09:41:25 +01:00
window . ui . showNotification ( 'Error' , `Error creating folder: ${ folderName } ` );
2026-02-08 22:44:42 +01:00
}
} catch ( error ) {
console . error ( `Network error creating folder ${ folderPath } :` , error );
}
}
// Upload files into their respective folders
let uploadedCount = 0 ;
const totalFiles = files . length ;
for ( let i = 0 ; i < totalFiles ; i ++ ) {
const file = files [ i ];
const parts = file . webkitRelativePath . split ( '/' );
const parentPath = parts . slice ( 0 , - 1 ). join ( '/' );
const targetFolderId = folderMap . get ( parentPath ) || currentFolderId ;
const formData = new FormData ();
formData . append ( 'folder_id' , targetFolderId );
formData . append ( 'file' , file );
try {
const response = await fetch ( '/api/files/upload' , {
method : 'POST' ,
body : formData ,
cache : 'no-store' ,
headers : {
... getAuthHeaders (),
'Cache-Control' : 'no-cache, no-store, must-revalidate'
}
});
uploadedCount ++ ;
const percentComplete = ( uploadedCount / totalFiles ) * 100 ;
progressBar . style . width = percentComplete + '%' ;
if ( response . ok ) {
console . log ( `Uploaded: ${ file . webkitRelativePath } ` );
} else {
console . error ( `Error uploading ${ file . webkitRelativePath } :` , await response . text ());
}
} catch ( error ) {
console . error ( `Network error uploading ${ file . webkitRelativePath } :` , error );
}
}
// Finish up
2026-02-12 09:41:25 +01:00
window . ui . showNotification ( 'Folder uploaded' , ` ${ uploadedCount } files uploaded successfully` );
2026-02-08 22:44:42 +01:00
await new Promise ( resolve => setTimeout ( resolve , 800 ));
try {
await window . loadFiles ({ forceRefresh : true });
} catch ( reloadError ) {
console . error ( 'Error reloading files:' , reloadError );
}
setTimeout (() => {
const dropzone = document . getElementById ( 'dropzone' );
if ( dropzone ) dropzone . style . display = 'none' ;
uploadProgressDiv . style . display = 'none' ;
}, 500 );
},
2025-03-19 23:28:29 +01:00
/**
* Create a new folder
* @param {string} name - Folder name
*/
async createFolder ( name ) {
try {
2025-04-01 21:14:09 +02:00
console . log ( 'Creating folder with name:' , name );
2026-02-12 09:41:25 +01:00
// Send the actual request to the backend to create the folder
2025-03-19 23:28:29 +01:00
const response = await fetch ( '/api/folders' , {
method : 'POST' ,
headers : {
2026-02-08 22:44:42 +01:00
... getAuthHeaders (),
2025-04-12 12:37:12 +02:00
'Content-Type' : 'application/json' ,
'Cache-Control' : 'no-cache, no-store, must-revalidate'
2025-03-19 23:28:29 +01:00
},
body : JSON . stringify ({
name : name ,
parent_id : window . app . currentPath || null
})
});
if ( response . ok ) {
2026-02-12 09:41:25 +01:00
// Get the created folder from the backend
2025-04-12 12:37:12 +02:00
const folder = await response . json ();
console . log ( 'Folder created successfully:' , folder );
2026-02-12 09:41:25 +01:00
// Add the folder to the view immediately for instant feedback
2025-04-12 12:37:12 +02:00
window . ui . addFolderToView ( folder );
2026-02-12 09:41:25 +01:00
// Wait to allow the backend to save the changes
2025-04-12 12:37:12 +02:00
await new Promise ( resolve => setTimeout ( resolve , 1000 ));
2026-02-12 09:41:25 +01:00
// Reload files to refresh the view
2025-04-12 12:37:12 +02:00
await window . loadFiles ({ forceRefresh : true });
2026-02-12 09:41:25 +01:00
window . ui . showNotification ( 'Folder created' , `" ${ name } " created successfully` );
2025-03-19 23:28:29 +01:00
} else {
const errorData = await response . text ();
console . error ( 'Create folder error:' , errorData );
2026-02-12 09:41:25 +01:00
window . ui . showNotification ( 'Error' , 'Error creating the folder' );
2025-03-19 23:28:29 +01:00
}
} catch ( error ) {
console . error ( 'Error creating folder:' , error );
2026-02-12 09:41:25 +01:00
window . ui . showNotification ( 'Error' , 'Error creating the folder' );
2025-03-19 23:28:29 +01:00
}
},
/**
* Move a file to another folder
* @param {string} fileId - File ID
* @param {string} targetFolderId - Target folder ID
* @returns {Promise<boolean>} - Success status
*/
async moveFile ( fileId , targetFolderId ) {
try {
const response = await fetch ( `/api/files/ ${ fileId } /move` , {
method : 'PUT' ,
headers : {
2026-02-08 22:44:42 +01:00
... getAuthHeaders (),
2025-03-19 23:28:29 +01:00
'Content-Type' : 'application/json'
},
body : JSON . stringify ({
folder_id : targetFolderId === "" ? null : targetFolderId
})
});
if ( response . ok ) {
// Reload files after moving
await window . loadFiles ();
2026-02-12 09:41:25 +01:00
window . ui . showNotification ( 'File moved' , 'File moved successfully' );
2025-03-19 23:28:29 +01:00
return true ;
} else {
2026-02-12 09:41:25 +01:00
let errorMessage = 'Unknown error' ;
2025-03-19 23:28:29 +01:00
try {
const errorData = await response . json ();
2026-02-12 09:41:25 +01:00
errorMessage = errorData . error || 'Unknown error' ;
2025-03-19 23:28:29 +01:00
} catch ( e ) {
2026-02-12 09:41:25 +01:00
errorMessage = 'Error processing server response' ;
2025-03-19 23:28:29 +01:00
}
2026-02-12 09:41:25 +01:00
window . ui . showNotification ( 'Error' , `Error moving the file: ${ errorMessage } ` );
2025-03-19 23:28:29 +01:00
return false ;
}
} catch ( error ) {
console . error ( 'Error moving file:' , error );
2026-02-12 09:41:25 +01:00
window . ui . showNotification ( 'Error' , 'Error moving the file' );
2025-03-19 23:28:29 +01:00
return false ;
}
},
/**
* Move a folder to another folder
* @param {string} folderId - Folder ID
* @param {string} targetFolderId - Target folder ID
* @returns {Promise<boolean>} - Success status
*/
async moveFolder ( folderId , targetFolderId ) {
try {
const response = await fetch ( `/api/folders/ ${ folderId } /move` , {
method : 'PUT' ,
headers : {
2026-02-08 22:44:42 +01:00
... getAuthHeaders (),
2025-03-19 23:28:29 +01:00
'Content-Type' : 'application/json'
},
body : JSON . stringify ({
parent_id : targetFolderId === "" ? null : targetFolderId
})
});
if ( response . ok ) {
// Reload files after moving
await window . loadFiles ();
2026-02-12 09:41:25 +01:00
window . ui . showNotification ( 'Folder moved' , 'Folder moved successfully' );
2025-03-19 23:28:29 +01:00
return true ;
} else {
2026-02-12 09:41:25 +01:00
let errorMessage = 'Unknown error' ;
2025-03-19 23:28:29 +01:00
try {
const errorData = await response . json ();
2026-02-12 09:41:25 +01:00
errorMessage = errorData . error || 'Unknown error' ;
2025-03-19 23:28:29 +01:00
} catch ( e ) {
2026-02-12 09:41:25 +01:00
errorMessage = 'Error processing server response' ;
2025-03-19 23:28:29 +01:00
}
2026-02-12 09:41:25 +01:00
window . ui . showNotification ( 'Error' , `Error moving the folder: ${ errorMessage } ` );
2025-03-19 23:28:29 +01:00
return false ;
}
} catch ( error ) {
console . error ( 'Error moving folder:' , error );
2026-02-12 09:41:25 +01:00
window . ui . showNotification ( 'Error' , 'Error moving the folder' );
2025-03-19 23:28:29 +01:00
return false ;
}
},
2026-02-08 22:44:42 +01:00
/**
* Rename a file
* @param {string} fileId - File ID
* @param {string} newName - New file name
* @returns {Promise<boolean>} - Success status
*/
async renameFile ( fileId , newName ) {
try {
console . log ( `Renaming file ${ fileId } to " ${ newName } "` );
const response = await fetch ( `/api/files/ ${ fileId } /rename` , {
method : 'PUT' ,
headers : {
... getAuthHeaders (),
'Content-Type' : 'application/json'
},
body : JSON . stringify ({ name : newName })
});
console . log ( 'Response status:' , response . status );
if ( response . ok ) {
window . ui . showNotification (
2026-02-12 09:41:25 +01:00
window . i18n ? window . i18n . t ( 'notifications.file_renamed' ) : 'File renamed' ,
window . i18n ? window . i18n . t ( 'notifications.file_renamed_to' , { name : newName }) : `File renamed to " ${ newName } "`
2026-02-08 22:44:42 +01:00
);
return true ;
} else {
const errorText = await response . text ();
console . error ( 'Error response:' , errorText );
2026-02-12 09:41:25 +01:00
let errorMessage = 'Unknown error' ;
2026-02-08 22:44:42 +01:00
try {
const errorData = JSON . parse ( errorText );
errorMessage = errorData . error || response . statusText ;
} catch ( e ) {
errorMessage = errorText || response . statusText ;
}
2026-02-12 09:41:25 +01:00
window . ui . showNotification ( 'Error' , `Error renaming the file: ${ errorMessage } ` );
2026-02-08 22:44:42 +01:00
return false ;
}
} catch ( error ) {
console . error ( 'Error renaming file:' , error );
2026-02-12 09:41:25 +01:00
window . ui . showNotification ( 'Error' , 'Error renaming the file' );
2026-02-08 22:44:42 +01:00
return false ;
}
},
2025-03-19 23:28:29 +01:00
/**
* Rename a folder
* @param {string} folderId - Folder ID
* @param {string} newName - New folder name
* @returns {Promise<boolean>} - Success status
*/
async renameFolder ( folderId , newName ) {
try {
console . log ( `Renaming folder ${ folderId } to " ${ newName } "` );
const response = await fetch ( `/api/folders/ ${ folderId } /rename` , {
method : 'PUT' ,
headers : {
2026-02-08 22:44:42 +01:00
... getAuthHeaders (),
2025-03-19 23:28:29 +01:00
'Content-Type' : 'application/json'
},
body : JSON . stringify ({ name : newName })
});
console . log ( 'Response status:' , response . status );
if ( response . ok ) {
2026-02-12 09:41:25 +01:00
window . ui . showNotification ( 'Folder renamed' , `Folder renamed to " ${ newName } "` );
2025-03-19 23:28:29 +01:00
return true ;
} else {
const errorText = await response . text ();
console . error ( 'Error response:' , errorText );
2026-02-12 09:41:25 +01:00
let errorMessage = 'Unknown error' ;
2025-03-19 23:28:29 +01:00
try {
// Try to parse as JSON
const errorData = JSON . parse ( errorText );
errorMessage = errorData . error || response . statusText ;
} catch ( e ) {
// If not JSON, use text as is
errorMessage = errorText || response . statusText ;
}
2026-02-12 09:41:25 +01:00
window . ui . showNotification ( 'Error' , `Error renaming the folder: ${ errorMessage } ` );
2025-03-19 23:28:29 +01:00
return false ;
}
} catch ( error ) {
console . error ( 'Error renaming folder:' , error );
2026-02-12 09:41:25 +01:00
window . ui . showNotification ( 'Error' , 'Error renaming the folder' );
2025-03-19 23:28:29 +01:00
return false ;
}
},
/**
2025-03-24 17:49:53 +01:00
* Move a file to trash
2025-03-19 23:28:29 +01:00
* @param {string} fileId - File ID
2025-03-24 17:49:53 +01:00
* @param {string} fileName - File name
2025-03-19 23:28:29 +01:00
* @returns {Promise<boolean>} - Success status
*/
async deleteFile ( fileId , fileName ) {
2026-02-08 22:44:42 +01:00
const confirmed = await showConfirmDialog ({
2026-02-12 09:41:25 +01:00
title : window . i18n ? window . i18n . t ( 'dialogs.confirm_delete' ) : 'Move to trash' ,
message : window . i18n ? window . i18n . t ( 'dialogs.confirm_delete_file' , { name : fileName }) : `Are you sure you want to move the file " ${ fileName } " to trash?` ,
confirmText : window . i18n ? window . i18n . t ( 'actions.delete' ) : 'Delete' ,
2026-02-08 22:44:42 +01:00
});
if ( ! confirmed ) return false ;
2025-03-19 23:28:29 +01:00
try {
2025-03-24 17:49:53 +01:00
// Use the trash API endpoint
const response = await fetch ( `/api/trash/files/ ${ fileId } ` , {
2026-02-08 22:44:42 +01:00
method : 'DELETE' ,
headers : getAuthHeaders ()
2025-03-19 23:28:29 +01:00
});
if ( response . ok ) {
window . loadFiles ();
2026-02-12 09:41:25 +01:00
window . ui . showNotification ( 'File moved to trash' , `" ${ fileName } " moved to trash` );
2025-03-19 23:28:29 +01:00
return true ;
} else {
2025-03-24 17:49:53 +01:00
// Fallback to direct deletion if trash fails
const fallbackResponse = await fetch ( `/api/files/ ${ fileId } ` , {
2026-02-08 22:44:42 +01:00
method : 'DELETE' ,
headers : getAuthHeaders ()
2025-03-24 17:49:53 +01:00
});
if ( fallbackResponse . ok ) {
window . loadFiles ();
2026-02-12 09:41:25 +01:00
window . ui . showNotification ( 'File deleted' , `" ${ fileName } " deleted successfully` );
2025-03-24 17:49:53 +01:00
return true ;
} else {
2026-02-12 09:41:25 +01:00
window . ui . showNotification ( 'Error' , 'Error deleting the file' );
2025-03-24 17:49:53 +01:00
return false ;
}
2025-03-19 23:28:29 +01:00
}
} catch ( error ) {
console . error ( 'Error deleting file:' , error );
2026-02-12 09:41:25 +01:00
window . ui . showNotification ( 'Error' , 'Error deleting the file' );
2025-03-19 23:28:29 +01:00
return false ;
}
},
/**
2025-03-24 17:49:53 +01:00
* Move a folder to trash
2025-03-19 23:28:29 +01:00
* @param {string} folderId - Folder ID
* @param {string} folderName - Folder name
* @returns {Promise<boolean>} - Success status
*/
async deleteFolder ( folderId , folderName ) {
2026-02-08 22:44:42 +01:00
const confirmed = await showConfirmDialog ({
2026-02-12 09:41:25 +01:00
title : window . i18n ? window . i18n . t ( 'dialogs.confirm_delete' ) : 'Move to trash' ,
message : window . i18n ? window . i18n . t ( 'dialogs.confirm_delete_folder' , { name : folderName }) : `Are you sure you want to move the folder " ${ folderName } " and all its contents to trash?` ,
confirmText : window . i18n ? window . i18n . t ( 'actions.delete' ) : 'Delete' ,
2026-02-08 22:44:42 +01:00
});
if ( ! confirmed ) return false ;
2025-03-19 23:28:29 +01:00
try {
2025-03-24 17:49:53 +01:00
// Use the trash API endpoint
const response = await fetch ( `/api/trash/folders/ ${ folderId } ` , {
2026-02-08 22:44:42 +01:00
method : 'DELETE' ,
headers : getAuthHeaders ()
2025-03-19 23:28:29 +01:00
});
if ( response . ok ) {
// If we're inside the folder we just deleted, go back up
if ( window . app . currentPath === folderId ) {
window . app . currentPath = '' ;
window . ui . updateBreadcrumb ( '' );
}
window . loadFiles ();
2026-02-12 09:41:25 +01:00
window . ui . showNotification ( 'Folder moved to trash' , `" ${ folderName } " moved to trash` );
2025-03-19 23:28:29 +01:00
return true ;
} else {
2025-03-24 17:49:53 +01:00
// Fallback to direct deletion if trash fails
const fallbackResponse = await fetch ( `/api/folders/ ${ folderId } ` , {
2026-02-08 22:44:42 +01:00
method : 'DELETE' ,
headers : getAuthHeaders ()
2025-03-24 17:49:53 +01:00
});
if ( fallbackResponse . ok ) {
// If we're inside the folder we just deleted, go back up
if ( window . app . currentPath === folderId ) {
window . app . currentPath = '' ;
window . ui . updateBreadcrumb ( '' );
}
window . loadFiles ();
2026-02-12 09:41:25 +01:00
window . ui . showNotification ( 'Folder deleted' , `" ${ folderName } " deleted successfully` );
2025-03-24 17:49:53 +01:00
return true ;
} else {
2026-02-12 09:41:25 +01:00
window . ui . showNotification ( 'Error' , 'Error deleting the folder' );
2025-03-24 17:49:53 +01:00
return false ;
}
2025-03-19 23:28:29 +01:00
}
} catch ( error ) {
console . error ( 'Error deleting folder:' , error );
2026-02-12 09:41:25 +01:00
window . ui . showNotification ( 'Error' , 'Error deleting the folder' );
2025-03-19 23:28:29 +01:00
return false ;
}
2025-03-24 17:49:53 +01:00
},
/**
2026-02-12 09:41:25 +01:00
* Get trash items
* @returns {Promise<Array>} - List of trash items
2025-03-24 17:49:53 +01:00
*/
async getTrashItems () {
try {
2026-02-08 22:44:42 +01:00
const response = await fetch ( '/api/trash' , {
headers : getAuthHeaders ()
});
2025-03-24 17:49:53 +01:00
if ( response . ok ) {
return await response . json ();
} else {
console . error ( 'Error fetching trash items:' , response . statusText );
return [];
}
} catch ( error ) {
console . error ( 'Error fetching trash items:' , error );
return [];
}
},
/**
2026-02-12 09:41:25 +01:00
* Restore an item from trash
* @param {string} trashId - Trash item ID
* @returns {Promise<boolean>} - Operation success
2025-03-24 17:49:53 +01:00
*/
async restoreFromTrash ( trashId ) {
try {
const response = await fetch ( `/api/trash/ ${ trashId } /restore` , {
method : 'POST' ,
headers : {
2026-02-08 22:44:42 +01:00
... getAuthHeaders (),
2025-03-24 17:49:53 +01:00
'Content-Type' : 'application/json'
},
body : JSON . stringify ({})
});
if ( response . ok ) {
2026-02-12 09:41:25 +01:00
window . ui . showNotification ( 'Item restored' , 'Item restored successfully' );
2025-03-24 17:49:53 +01:00
return true ;
} else {
2026-02-12 09:41:25 +01:00
window . ui . showNotification ( 'Error' , 'Error restoring the item' );
2025-03-24 17:49:53 +01:00
return false ;
}
} catch ( error ) {
console . error ( 'Error restoring item from trash:' , error );
2026-02-12 09:41:25 +01:00
window . ui . showNotification ( 'Error' , 'Error restoring the item' );
2025-03-24 17:49:53 +01:00
return false ;
}
},
/**
2026-02-12 09:41:25 +01:00
* Permanently delete a trash item
* @param {string} trashId - Trash item ID
* @returns {Promise<boolean>} - Operation success
2025-03-24 17:49:53 +01:00
*/
async deletePermanently ( trashId ) {
2026-02-08 22:44:42 +01:00
const confirmed = await showConfirmDialog ({
2026-02-12 09:41:25 +01:00
title : window . i18n ? window . i18n . t ( 'dialogs.confirm_permanent_delete' ) : 'Delete permanently' ,
message : window . i18n ? window . i18n . t ( 'dialogs.confirm_permanent_delete_msg' ) : 'Are you sure you want to permanently delete this item? This action cannot be undone.' ,
confirmText : window . i18n ? window . i18n . t ( 'actions.delete_permanently' ) : 'Delete permanently' ,
2026-02-08 22:44:42 +01:00
});
if ( ! confirmed ) return false ;
2025-03-24 17:49:53 +01:00
try {
const response = await fetch ( `/api/trash/ ${ trashId } ` , {
2026-02-08 22:44:42 +01:00
method : 'DELETE' ,
headers : getAuthHeaders ()
2025-03-24 17:49:53 +01:00
});
if ( response . ok ) {
2026-02-12 09:41:25 +01:00
window . ui . showNotification ( 'Item deleted' , 'Item permanently deleted' );
2025-03-24 17:49:53 +01:00
return true ;
} else {
2026-02-12 09:41:25 +01:00
window . ui . showNotification ( 'Error' , 'Error deleting the item' );
2025-03-24 17:49:53 +01:00
return false ;
}
} catch ( error ) {
console . error ( 'Error deleting item permanently:' , error );
2026-02-12 09:41:25 +01:00
window . ui . showNotification ( 'Error' , 'Error deleting the item' );
2025-03-24 17:49:53 +01:00
return false ;
}
},
/**
2026-02-12 09:41:25 +01:00
* Empty the trash
* @returns {Promise<boolean>} - Operation success
2025-03-24 17:49:53 +01:00
*/
async emptyTrash () {
2026-02-08 22:44:42 +01:00
const confirmed = await showConfirmDialog ({
2026-02-12 09:41:25 +01:00
title : window . i18n ? window . i18n . t ( 'dialogs.confirm_empty_trash' ) : 'Empty trash' ,
message : window . i18n ? window . i18n . t ( 'trash.empty_confirm' ) : 'Are you sure you want to empty the trash? This action will permanently delete all items.' ,
confirmText : window . i18n ? window . i18n . t ( 'actions.empty_trash' ) : 'Empty trash' ,
2026-02-08 22:44:42 +01:00
});
if ( ! confirmed ) return false ;
2025-03-24 17:49:53 +01:00
try {
const response = await fetch ( '/api/trash/empty' , {
2026-02-08 22:44:42 +01:00
method : 'DELETE' ,
headers : getAuthHeaders ()
2025-03-24 17:49:53 +01:00
});
if ( response . ok ) {
2026-02-12 09:41:25 +01:00
window . ui . showNotification ( 'Trash emptied' , 'The trash has been emptied successfully' );
2025-03-24 17:49:53 +01:00
return true ;
} else {
2026-02-12 09:41:25 +01:00
window . ui . showNotification ( 'Error' , 'Error emptying the trash' );
2025-03-24 17:49:53 +01:00
return false ;
}
} catch ( error ) {
console . error ( 'Error emptying trash:' , error );
2026-02-12 09:41:25 +01:00
window . ui . showNotification ( 'Error' , 'Error emptying the trash' );
2025-03-24 17:49:53 +01:00
return false ;
}
2025-04-02 01:22:05 +02:00
},
/**
2026-02-12 09:41:25 +01:00
* Download a file
* @param {string} fileId - File ID
* @param {string} fileName - File name
2025-04-02 01:22:05 +02:00
*/
2026-02-08 22:44:42 +01:00
async downloadFile ( fileId , fileName ) {
try {
const response = await fetch ( `/api/files/ ${ fileId } ` , {
headers : getAuthHeaders ()
});
if ( response . ok ) {
const blob = await response . blob ();
const url = URL . createObjectURL ( blob );
const link = document . createElement ( 'a' );
link . href = url ;
link . download = fileName ;
document . body . appendChild ( link );
link . click ();
document . body . removeChild ( link );
URL . revokeObjectURL ( url );
} else {
2026-02-12 09:41:25 +01:00
window . ui . showNotification ( 'Error' , 'Error downloading the file' );
2026-02-08 22:44:42 +01:00
}
} catch ( error ) {
console . error ( 'Error downloading file:' , error );
2026-02-12 09:41:25 +01:00
window . ui . showNotification ( 'Error' , 'Error downloading the file' );
2026-02-08 22:44:42 +01:00
}
2025-04-02 01:22:05 +02:00
},
/**
2026-02-12 09:41:25 +01:00
* Download a folder as ZIP
* @param {string} folderId - Folder ID
* @param {string} folderName - Folder name
2025-04-02 01:22:05 +02:00
*/
async downloadFolder ( folderId , folderName ) {
try {
// Show notification to user
2026-02-12 09:41:25 +01:00
window . ui . showNotification ( 'Preparing download' , 'Preparing the folder for download...' );
2025-04-02 01:22:05 +02:00
2026-02-08 22:44:42 +01:00
const response = await fetch ( `/api/folders/ ${ folderId } /download?format=zip` , {
headers : getAuthHeaders ()
});
if ( response . ok ) {
const blob = await response . blob ();
const url = URL . createObjectURL ( blob );
const link = document . createElement ( 'a' );
link . href = url ;
link . download = ` ${ folderName } .zip` ;
document . body . appendChild ( link );
link . click ();
document . body . removeChild ( link );
URL . revokeObjectURL ( url );
} else {
2026-02-12 09:41:25 +01:00
window . ui . showNotification ( 'Error' , 'Error downloading the folder' );
2026-02-08 22:44:42 +01:00
}
2025-04-02 01:22:05 +02:00
} catch ( error ) {
console . error ( 'Error downloading folder:' , error );
2026-02-12 09:41:25 +01:00
window . ui . showNotification ( 'Error' , 'Error downloading the folder' );
2025-04-02 01:22:05 +02:00
}
2025-03-19 23:28:29 +01:00
}
};
// Expose file operations module globally
window . fileOps = fileOps ;