diff --git a/frontend/src/api/migration.js b/frontend/src/api/migration.js index ae2132f57a9f..398aa9547ce6 100644 --- a/frontend/src/api/migration.js +++ b/frontend/src/api/migration.js @@ -5,12 +5,12 @@ import { store } from "../store/store"; const migrationBase = baseURL + "migration/"; const migrationURLs = { + upload: migrationBase + "upload/", + delete: (file) => `${migrationBase}${file}/delete/`, chowdownURL: migrationBase + "chowdown/repo/", nextcloudAvaiable: migrationBase + "nextcloud/available/", nextcloudImport: (selection) => `${migrationBase}nextcloud/${selection}/import/`, - nextcloudDelete: (selection) => - `${migrationBase}nextcloud/${selection}/delete/`, }; export default { @@ -28,4 +28,16 @@ export default { let response = await apiReq.post(migrationURLs.nextcloudImport(selected)); return response.data; }, + async uploadFile(form_data) { + let response = await apiReq.post(migrationURLs.upload, form_data, { + headers: { + "Content-Type": "multipart/form-data", + }, + }); + return response.data; + }, + async delete(file_folder_name) { + let response = await apiReq.delete(migrationURLs.delete(file_folder_name)); + return response.data; + }, }; diff --git a/frontend/src/components/Settings/Migration/NextcloudCard.vue b/frontend/src/components/Settings/Migration/NextcloudCard.vue index 0e5980be7f74..ede045c09bca 100644 --- a/frontend/src/components/Settings/Migration/NextcloudCard.vue +++ b/frontend/src/components/Settings/Migration/NextcloudCard.vue @@ -7,7 +7,7 @@

- + - + Migrate + + + Delete + + + + + + + + import api from "../../../api"; import SuccessFailureAlert from "../../UI/SuccessFailureAlert"; +import UploadMigrationButton from "./UploadMigrationButton"; +import Confirmation from "../../UI/Confirmation"; export default { components: { SuccessFailureAlert, + UploadMigrationButton, + Confirmation, }, data() { return { @@ -48,9 +70,12 @@ export default { }; }, async mounted() { - this.availableImports = await api.migrations.getNextcloudImports(); + this.getAvaiableImports(); }, methods: { + async getAvaiableImports() { + this.availableImports = await api.migrations.getNextcloudImports(); + }, async importRecipes() { if (this.$refs.form.validate()) { this.$emit("loading"); @@ -61,6 +86,15 @@ export default { this.$emit("finished"); } }, + deleteImportValidation() { + if (this.$refs.form.validate()) { + this.$refs.deleteThemeConfirm.open(); + } + }, + async deleteImport() { + await api.migrations.delete(this.selectedImport); + this.getAvaiableImports(); + }, }, }; diff --git a/frontend/src/components/Settings/Migration/UploadMigrationButton.vue b/frontend/src/components/Settings/Migration/UploadMigrationButton.vue new file mode 100644 index 000000000000..c9072cc2f57d --- /dev/null +++ b/frontend/src/components/Settings/Migration/UploadMigrationButton.vue @@ -0,0 +1,42 @@ + + + + + \ No newline at end of file diff --git a/mealie/routes/migration_routes.py b/mealie/routes/migration_routes.py index 350030d0e8c1..8a7430c6a2a6 100644 --- a/mealie/routes/migration_routes.py +++ b/mealie/routes/migration_routes.py @@ -1,4 +1,6 @@ -from fastapi import APIRouter, HTTPException +import shutil + +from fastapi import APIRouter, File, HTTPException, UploadFile from models.migration_models import ChowdownURL from services.migrations.chowdown import chowdown_migrate as chowdow_migrate from services.migrations.nextcloud import migrate as nextcloud_migrate @@ -46,3 +48,33 @@ async def import_nextcloud_directory(selection: str): """ Imports all the recipes in a given directory """ return nextcloud_migrate(selection) + + +@router.delete("/api/migration/{file_folder_name}/delete/", tags=["Migration"]) +async def delete_migration_data(file_folder_name: str): + """ Removes migration data from the file system """ + + remove_path = MIGRATION_DIR.joinpath(file_folder_name) + + if remove_path.is_file(): + remove_path.unlink() + elif remove_path.is_dir(): + shutil.rmtree(remove_path) + else: + SnackResponse.error("File/Folder not found.") + + return SnackResponse.info(f"Migration Data Remove: {remove_path.absolute()}") + + +@router.post("/api/migration/upload/", tags=["Migration"]) +async def upload_nextcloud_zipfile(archive: UploadFile = File(...)): + """ Upload a .zip File to later be imported into Mealie """ + dest = MIGRATION_DIR.joinpath(archive.filename) + + with dest.open("wb") as buffer: + shutil.copyfileobj(archive.file, buffer) + + if dest.is_file: + return SnackResponse.success("Migration data uploaded") + else: + return SnackResponse.error("Failure uploading file")