2025-03-19 23:28:29 +01:00
/**
* OxiCloud - File Operations Module
* This file handles file and folder operations (create, move, delete, rename, upload)
*/
// 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 ();
formData . append ( 'file' , file );
if ( window . app . currentPath ) {
formData . append ( 'folder_id' , window . app . currentPath );
}
try {
2025-03-23 22:44:18 +01:00
console . log ( `Uploading file to current path: ${ window . app . currentPath || 'root' } ` );
// Usamos la URL correcta para la subida de archivos
console . log ( 'Formulario a enviar:' , {
file : file . name ,
size : file . size ,
folder_id : window . app . currentPath || 'root'
});
2025-03-19 23:28:29 +01:00
const response = await fetch ( '/api/files/upload' , {
method : 'POST' ,
body : formData
});
2025-03-23 22:44:18 +01:00
console . log ( 'Respuesta del servidor:' , {
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-03-19 23:28:29 +01:00
if ( i === totalFiles - 1 ) {
// Last file uploaded
2025-03-23 22:44:18 +01:00
console . log ( 'Recargando lista de archivos después de subida' );
2025-03-19 23:28:29 +01:00
window . loadFiles ();
setTimeout (() => {
document . getElementById ( 'dropzone' ). style . display = 'none' ;
uploadProgressDiv . style . display = 'none' ;
}, 1000 );
// Show success notification
window . ui . showNotification ( 'Archivo subido' , ` ${ file . name } completado` );
}
} else {
const errorData = await response . text ();
console . error ( 'Upload error:' , errorData );
window . ui . showNotification ( 'Error' , `Error al subir el archivo: ${ file . name } ` );
}
} catch ( error ) {
console . error ( 'Network error during upload:' , error );
window . ui . showNotification ( 'Error' , `Error de red al subir el archivo: ${ file . name } ` );
}
}
},
/**
* Create a new folder
* @param {string} name - Folder name
*/
async createFolder ( name ) {
try {
2025-04-01 21:14:09 +02:00
// 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
2025-03-19 23:28:29 +01:00
const response = await fetch('/api/folders', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
name: name,
parent_id: window.app.currentPath || null
})
});
if (response.ok) {
window.loadFiles();
window.ui.showNotification('Carpeta creada', `"${name}" creada correctamente`);
} else {
const errorData = await response.text();
console.error('Create folder error:', errorData);
window.ui.showNotification('Error', 'Error al crear la carpeta');
}
2025-04-01 21:14:09 +02:00
*/
2025-03-19 23:28:29 +01:00
} catch ( error ) {
console . error ( 'Error creating folder:' , error );
window . ui . showNotification ( 'Error' , 'Error al crear la carpeta' );
}
},
/**
* 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 : {
'Content-Type' : 'application/json'
},
body : JSON . stringify ({
folder_id : targetFolderId === "" ? null : targetFolderId
})
});
if ( response . ok ) {
// Reload files after moving
await window . loadFiles ();
window . ui . showNotification ( 'Archivo movido' , 'Archivo movido correctamente' );
return true ;
} else {
let errorMessage = 'Error desconocido' ;
try {
const errorData = await response . json ();
errorMessage = errorData . error || 'Error desconocido' ;
} catch ( e ) {
errorMessage = 'Error al procesar la respuesta del servidor' ;
}
window . ui . showNotification ( 'Error' , `Error al mover el archivo: ${ errorMessage } ` );
return false ;
}
} catch ( error ) {
console . error ( 'Error moving file:' , error );
window . ui . showNotification ( 'Error' , 'Error al mover el archivo' );
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 : {
'Content-Type' : 'application/json'
},
body : JSON . stringify ({
parent_id : targetFolderId === "" ? null : targetFolderId
})
});
if ( response . ok ) {
// Reload files after moving
await window . loadFiles ();
window . ui . showNotification ( 'Carpeta movida' , 'Carpeta movida correctamente' );
return true ;
} else {
let errorMessage = 'Error desconocido' ;
try {
const errorData = await response . json ();
errorMessage = errorData . error || 'Error desconocido' ;
} catch ( e ) {
errorMessage = 'Error al procesar la respuesta del servidor' ;
}
window . ui . showNotification ( 'Error' , `Error al mover la carpeta: ${ errorMessage } ` );
return false ;
}
} catch ( error ) {
console . error ( 'Error moving folder:' , error );
window . ui . showNotification ( 'Error' , 'Error al mover la carpeta' );
return false ;
}
},
/**
* 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 : {
'Content-Type' : 'application/json'
},
body : JSON . stringify ({ name : newName })
});
console . log ( 'Response status:' , response . status );
if ( response . ok ) {
window . ui . showNotification ( 'Carpeta renombrada' , `Carpeta renombrada a " ${ newName } "` );
return true ;
} else {
const errorText = await response . text ();
console . error ( 'Error response:' , errorText );
let errorMessage = 'Error desconocido' ;
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 ;
}
window . ui . showNotification ( 'Error' , `Error al renombrar la carpeta: ${ errorMessage } ` );
return false ;
}
} catch ( error ) {
console . error ( 'Error renaming folder:' , error );
window . ui . showNotification ( 'Error' , 'Error al renombrar la carpeta' );
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 ) {
2025-03-24 17:49:53 +01:00
if ( ! confirm ( `¿Estás seguro de que quieres mover a la papelera el archivo " ${ fileName } "?` )) {
2025-03-19 23:28:29 +01:00
return false ;
}
try {
2025-03-24 17:49:53 +01:00
// Use the trash API endpoint
const response = await fetch ( `/api/trash/files/ ${ fileId } ` , {
2025-03-19 23:28:29 +01:00
method : 'DELETE'
});
if ( response . ok ) {
window . loadFiles ();
2025-03-24 17:49:53 +01:00
window . ui . showNotification ( 'Archivo movido a papelera' , `" ${ fileName } " movido a la papelera` );
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 } ` , {
method : 'DELETE'
});
if ( fallbackResponse . ok ) {
window . loadFiles ();
window . ui . showNotification ( 'Archivo eliminado' , `" ${ fileName } " eliminado correctamente` );
return true ;
} else {
window . ui . showNotification ( 'Error' , 'Error al eliminar el archivo' );
return false ;
}
2025-03-19 23:28:29 +01:00
}
} catch ( error ) {
console . error ( 'Error deleting file:' , error );
window . ui . showNotification ( 'Error' , 'Error al eliminar el archivo' );
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 ) {
2025-03-24 17:49:53 +01:00
if ( ! confirm ( `¿Estás seguro de que quieres mover a la papelera la carpeta " ${ folderName } " y todo su contenido?` )) {
2025-03-19 23:28:29 +01:00
return false ;
}
try {
2025-03-24 17:49:53 +01:00
// Use the trash API endpoint
const response = await fetch ( `/api/trash/folders/ ${ folderId } ` , {
2025-03-19 23:28:29 +01:00
method : 'DELETE'
});
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 ();
2025-03-24 17:49:53 +01:00
window . ui . showNotification ( 'Carpeta movida a papelera' , `" ${ folderName } " movida a la papelera` );
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 } ` , {
method : 'DELETE'
});
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 ();
window . ui . showNotification ( 'Carpeta eliminada' , `" ${ folderName } " eliminada correctamente` );
return true ;
} else {
window . ui . showNotification ( 'Error' , 'Error al eliminar la carpeta' );
return false ;
}
2025-03-19 23:28:29 +01:00
}
} catch ( error ) {
console . error ( 'Error deleting folder:' , error );
window . ui . showNotification ( 'Error' , 'Error al eliminar la carpeta' );
return false ;
}
2025-03-24 17:49:53 +01:00
},
/**
* Obtener elementos de la papelera
* @returns {Promise<Array>} - Lista de elementos en la papelera
*/
async getTrashItems () {
try {
const response = await fetch ( '/api/trash' );
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 [];
}
},
/**
* Restaurar un elemento desde la papelera
* @param {string} trashId - ID del elemento en la papelera
* @returns {Promise<boolean>} - Éxito de la operación
*/
async restoreFromTrash ( trashId ) {
try {
const response = await fetch ( `/api/trash/ ${ trashId } /restore` , {
method : 'POST' ,
headers : {
'Content-Type' : 'application/json'
},
body : JSON . stringify ({})
});
if ( response . ok ) {
window . ui . showNotification ( 'Elemento restaurado' , 'Elemento restaurado correctamente' );
return true ;
} else {
window . ui . showNotification ( 'Error' , 'Error al restaurar el elemento' );
return false ;
}
} catch ( error ) {
console . error ( 'Error restoring item from trash:' , error );
window . ui . showNotification ( 'Error' , 'Error al restaurar el elemento' );
return false ;
}
},
/**
* Eliminar permanentemente un elemento de la papelera
* @param {string} trashId - ID del elemento en la papelera
* @returns {Promise<boolean>} - Éxito de la operación
*/
async deletePermanently ( trashId ) {
if ( ! confirm ( '¿Estás seguro de que quieres eliminar permanentemente este elemento? Esta acción no se puede deshacer.' )) {
return false ;
}
try {
const response = await fetch ( `/api/trash/ ${ trashId } ` , {
method : 'DELETE'
});
if ( response . ok ) {
window . ui . showNotification ( 'Elemento eliminado' , 'Elemento eliminado permanentemente' );
return true ;
} else {
window . ui . showNotification ( 'Error' , 'Error al eliminar el elemento' );
return false ;
}
} catch ( error ) {
console . error ( 'Error deleting item permanently:' , error );
window . ui . showNotification ( 'Error' , 'Error al eliminar el elemento' );
return false ;
}
},
/**
* Vaciar la papelera
* @returns {Promise<boolean>} - Éxito de la operación
*/
async emptyTrash () {
2025-03-27 01:13:34 +01:00
const confirmMsg = window . i18n ? window . i18n . t ( 'trash.empty_confirm' ) : '¿Estás seguro de que quieres vaciar la papelera? Esta acción eliminará permanentemente todos los elementos.' ;
if ( ! confirm ( confirmMsg )) {
2025-03-24 17:49:53 +01:00
return false ;
}
try {
const response = await fetch ( '/api/trash/empty' , {
method : 'DELETE'
});
if ( response . ok ) {
window . ui . showNotification ( 'Papelera vaciada' , 'La papelera ha sido vaciada correctamente' );
return true ;
} else {
window . ui . showNotification ( 'Error' , 'Error al vaciar la papelera' );
return false ;
}
} catch ( error ) {
console . error ( 'Error emptying trash:' , error );
window . ui . showNotification ( 'Error' , 'Error al vaciar la papelera' );
return false ;
}
2025-04-02 01:22:05 +02:00
},
/**
* Descargar un archivo
* @param {string} fileId - ID del archivo
* @param {string} fileName - Nombre del archivo
*/
downloadFile ( fileId , fileName ) {
// Create a link and trigger download
const link = document . createElement ( 'a' );
link . href = `/api/files/ ${ fileId } ` ;
link . download = fileName ;
link . target = '_blank' ;
document . body . appendChild ( link );
link . click ();
document . body . removeChild ( link );
},
/**
* Descargar una carpeta como ZIP
* @param {string} folderId - ID de la carpeta
* @param {string} folderName - Nombre de la carpeta
*/
async downloadFolder ( folderId , folderName ) {
try {
// Show notification to user
window . ui . showNotification ( 'Preparando descarga' , 'Preparando la carpeta para descargar...' );
// Request the server to create a ZIP of the folder
// Since the API might not support this directly, we will simply download with zip parameter
const link = document . createElement ( 'a' );
link . href = `/api/folders/ ${ folderId } /download?format=zip` ;
link . download = ` ${ folderName } .zip` ;
link . target = '_blank' ;
document . body . appendChild ( link );
link . click ();
document . body . removeChild ( link );
} catch ( error ) {
console . error ( 'Error downloading folder:' , error );
window . ui . showNotification ( 'Error' , 'Error al descargar la carpeta' );
}
2025-03-19 23:28:29 +01:00
}
};
// Expose file operations module globally
window . fileOps = fileOps ;