diff --git a/engine/src/api/routes.rs b/engine/src/api/routes.rs index f8a748e9..0cbcb1de 100644 --- a/engine/src/api/routes.rs +++ b/engine/src/api/routes.rs @@ -1254,8 +1254,9 @@ pub async fn remove( ) -> Result { let manager = controllers.lock().unwrap().get(*id).unwrap(); let config = manager.config.lock().unwrap().clone(); + let recursive = data.recursive; - match remove_file_or_folder(&config, &data.into_inner().source).await { + match remove_file_or_folder(&config, &data.into_inner().source, recursive).await { Ok(obj) => Ok(web::Json(obj)), Err(e) => Err(e), } diff --git a/engine/src/utils/files.rs b/engine/src/utils/files.rs index 57405fb2..66bb18dd 100644 --- a/engine/src/utils/files.rs +++ b/engine/src/utils/files.rs @@ -27,6 +27,8 @@ pub struct PathObject { files: Option>, #[serde(default)] pub folders_only: bool, + #[serde(default)] + pub recursive: bool, } impl PathObject { @@ -38,6 +40,7 @@ impl PathObject { folders: Some(vec![]), files: Some(vec![]), folders_only: false, + recursive: false, } } } @@ -312,6 +315,7 @@ pub async fn rename_file( pub async fn remove_file_or_folder( config: &PlayoutConfig, source_path: &str, + recursive: bool, ) -> Result<(), ServiceError> { let (source, _, _) = norm_abs_path(&config.channel.storage, source_path)?; @@ -320,15 +324,27 @@ pub async fn remove_file_or_folder( } if source.is_dir() { - match fs::remove_dir(source).await { - Ok(_) => return Ok(()), - Err(e) => { - error!("{e}"); - return Err(ServiceError::BadRequest( - "Delete folder failed! (Folder must be empty)".into(), - )); - } - }; + if recursive { + match fs::remove_dir_all(source).await { + Ok(_) => return Ok(()), + Err(e) => { + error!("{e}"); + return Err(ServiceError::BadRequest( + "Delete folder and its content failed!".into(), + )); + } + }; + } else { + match fs::remove_dir(source).await { + Ok(_) => return Ok(()), + Err(e) => { + error!("{e}"); + return Err(ServiceError::BadRequest( + "Delete folder failed! (Folder must be empty)".into(), + )); + } + }; + } } if source.is_file() { diff --git a/frontend/i18n/locales/de-DE.js b/frontend/i18n/locales/de-DE.js index e7537a40..dd7abd9d 100644 --- a/frontend/i18n/locales/de-DE.js +++ b/frontend/i18n/locales/de-DE.js @@ -110,6 +110,7 @@ export default { folderError: 'Fehler beim Erstellen des Ordners', uploadError: 'Fehler beim Hochladen', fileExists: 'Datei existiert bereits!', + recursive: 'Rekursiv', }, message: { savePreset: 'Voreinstellung speichern', diff --git a/frontend/i18n/locales/en-US.js b/frontend/i18n/locales/en-US.js index fa2d50a4..e8cf85e7 100644 --- a/frontend/i18n/locales/en-US.js +++ b/frontend/i18n/locales/en-US.js @@ -110,6 +110,7 @@ export default { folderError: 'Folder create error', uploadError: 'Upload error', fileExists: 'File exists already!', + recursive: 'Recursive', }, message: { savePreset: 'Save Preset', diff --git a/frontend/i18n/locales/pt-BR.js b/frontend/i18n/locales/pt-BR.js index 648433fe..0a9d2d13 100644 --- a/frontend/i18n/locales/pt-BR.js +++ b/frontend/i18n/locales/pt-BR.js @@ -110,6 +110,7 @@ export default { folderError: 'Erro ao criar pasta', uploadError: 'Erro ao carregar', fileExists: 'O arquivo já existe!', + recursive: 'Recursivo', }, message: { savePreset: 'Salvar predefinição', diff --git a/frontend/i18n/locales/ru-RU.js b/frontend/i18n/locales/ru-RU.js index 1f7d9c57..4dda70a6 100644 --- a/frontend/i18n/locales/ru-RU.js +++ b/frontend/i18n/locales/ru-RU.js @@ -110,6 +110,7 @@ export default { folderError: 'Ошибка Создания папки', uploadError: 'Ошибка Загрузки', fileExists: 'Файл уже имеется!', + recursive: 'Рекурсивный', }, message: { savePreset: 'Сохранить шаблон', diff --git a/frontend/pages/media.vue b/frontend/pages/media.vue index b4007ec1..9df1bc78 100644 --- a/frontend/pages/media.vue +++ b/frontend/pages/media.vue @@ -233,7 +233,17 @@ :title="t('media.deleteTitle')" :text="`${t('media.deleteQuestion')}:
${deleteName}`" :modal-action="deleteFileOrFolder" - /> + > +
+ +
+ +
+
+ { const horizontal = ref(false) const deleteName = ref('') +const recursive = ref(false) const renameOldName = ref('') const renameOldPath = ref('') const renameNewName = ref('') @@ -341,6 +352,7 @@ const showRenameModal = ref(false) const showCreateModal = ref(false) const showUploadModal = ref(false) const extensions = ref('') +const extensionsArr = ref([] as string[]) const folderName = ref({} as Folder) const inputFiles = ref([] as File[]) const fileInputName = ref() @@ -363,11 +375,11 @@ onMounted(async () => { extra_extensions = extra_extensions.split(',') } - const exts = [...config_extensions, ...extra_extensions].map((ext) => { + extensionsArr.value = [...config_extensions, ...extra_extensions].map((ext) => { return `.${ext}` }) - extensions.value = exts.join(', ') + extensions.value = extensionsArr.value.join(', ') if (!mediaStore.folderTree.parent || !mediaStore.currentPath) { await mediaStore.getTree('') @@ -497,7 +509,7 @@ async function deleteFileOrFolder(del: boolean) { await fetch(`/api/file/${configStore.channels[configStore.i].id}/remove/`, { method: 'POST', headers: { ...configStore.contentType, ...authStore.authHeader }, - body: JSON.stringify({ source: deleteName.value }), + body: JSON.stringify({ source: deleteName.value, recursive: recursive.value }), }) .then(async (response) => { if (response.status !== 200) { @@ -508,6 +520,8 @@ async function deleteFileOrFolder(del: boolean) { .catch((e) => { indexStore.msgAlert('error', `${t('media.deleteError')}: ${e}`, 5) }) + + recursive.value = false } deleteName.value = ''