mirror of
				https://github.com/mealie-recipes/mealie.git
				synced 2025-10-31 02:03:35 -04:00 
			
		
		
		
	upload nextcloud data from UI
This commit is contained in:
		| @@ -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; | ||||
|   }, | ||||
| }; | ||||
|   | ||||
| @@ -7,7 +7,7 @@ | ||||
|     </p> | ||||
|     <v-form ref="form"> | ||||
|       <v-row align="center"> | ||||
|         <v-col cols="12" md="5" sm="5"> | ||||
|         <v-col cols="12" md="5" sm="12"> | ||||
|           <v-select | ||||
|             :items="availableImports" | ||||
|             v-model="selectedImport" | ||||
| @@ -15,9 +15,27 @@ | ||||
|             :rules="[rules.required]" | ||||
|           ></v-select> | ||||
|         </v-col> | ||||
|         <v-col cols="12" md="2" sm="2"> | ||||
|         <v-col cols="12" md="2" sm="12"> | ||||
|           <v-btn text color="info" @click="importRecipes"> Migrate </v-btn> | ||||
|         </v-col> | ||||
|         <v-col cols="12" md="1" sm="12"> | ||||
|           <v-btn text color="error" @click="deleteImportValidation"> | ||||
|             Delete | ||||
|           </v-btn> | ||||
|           <Confirmation | ||||
|             title="Delete Data" | ||||
|             message="Are you sure you want to delete this migration data?" | ||||
|             color="error" | ||||
|             icon="mdi-alert-circle" | ||||
|             ref="deleteThemeConfirm" | ||||
|             v-on:confirm="deleteImport()" | ||||
|           /> | ||||
|         </v-col> | ||||
|       </v-row> | ||||
|       <v-row> | ||||
|         <v-col cols="12" md="5" sm="12"> | ||||
|           <UploadMigrationButton @uploaded="getAvaiableImports" /> | ||||
|         </v-col> | ||||
|       </v-row> | ||||
|     </v-form> | ||||
|     <SuccessFailureAlert | ||||
| @@ -32,9 +50,13 @@ | ||||
| <script> | ||||
| 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(); | ||||
|     }, | ||||
|   }, | ||||
| }; | ||||
| </script> | ||||
|   | ||||
| @@ -0,0 +1,42 @@ | ||||
| <template> | ||||
|   <v-form ref="file"> | ||||
|     <v-file-input | ||||
|       :loading="loading" | ||||
|       label="Upload an Archive" | ||||
|       v-model="file" | ||||
|       accept=".zip" | ||||
|       @change="upload" | ||||
|     > | ||||
|     </v-file-input> | ||||
|   </v-form> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
| import api from "../../../api"; | ||||
| export default { | ||||
|   data() { | ||||
|     return { | ||||
|       file: null, | ||||
|       loading: false, | ||||
|     }; | ||||
|   }, | ||||
|   methods: { | ||||
|     async upload() { | ||||
|       if (this.file != null) { | ||||
|         this.loading = true; | ||||
|         let formData = new FormData(); | ||||
|         formData.append("archive", this.file); | ||||
|  | ||||
|         await api.migrations.uploadFile(formData); | ||||
|  | ||||
|         this.loading = false; | ||||
|         this.$emit("uploaded"); | ||||
|         this.file = null; | ||||
|       } | ||||
|     }, | ||||
|   }, | ||||
| }; | ||||
| </script> | ||||
|  | ||||
| <style> | ||||
| </style> | ||||
| @@ -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") | ||||
|   | ||||
		Reference in New Issue
	
	Block a user