| 
									
										
										
										
											2021-08-21 00:46:43 -08:00
										 |  |  | <template> | 
					
						
							|  |  |  |   <v-container fluid> | 
					
						
							| 
									
										
										
										
											2022-03-13 15:42:22 -08:00
										 |  |  |     <BannerExperimental issue="https://github.com/hay-kot/mealie/issues/871"></BannerExperimental> | 
					
						
							| 
									
										
										
										
											2021-08-21 00:46:43 -08:00
										 |  |  |     <section> | 
					
						
							|  |  |  |       <!-- Delete Dialog --> | 
					
						
							|  |  |  |       <BaseDialog | 
					
						
							| 
									
										
										
										
											2021-11-25 14:17:02 -09:00
										 |  |  |         v-model="deleteDialog" | 
					
						
							| 
									
										
										
										
											2021-08-21 00:46:43 -08:00
										 |  |  |         :title="$t('settings.backup.delete-backup')" | 
					
						
							|  |  |  |         color="error" | 
					
						
							|  |  |  |         :icon="$globals.icons.alertCircle" | 
					
						
							|  |  |  |         @confirm="deleteBackup()" | 
					
						
							|  |  |  |       > | 
					
						
							|  |  |  |         <v-card-text> | 
					
						
							|  |  |  |           {{ $t("general.confirm-delete-generic") }} | 
					
						
							|  |  |  |         </v-card-text> | 
					
						
							|  |  |  |       </BaseDialog> | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       <!-- Import Dialog --> | 
					
						
							| 
									
										
										
										
											2022-03-13 15:42:22 -08:00
										 |  |  |       <BaseDialog v-model="importDialog" color="error" title="Backup Restore" :icon="$globals.icons.database"> | 
					
						
							| 
									
										
										
										
											2021-08-21 00:46:43 -08:00
										 |  |  |         <v-divider></v-divider> | 
					
						
							|  |  |  |         <v-card-text> | 
					
						
							| 
									
										
										
										
											2022-03-13 15:42:22 -08:00
										 |  |  |           Restoring this backup will overwrite all the current data in your database and in the data directory and | 
					
						
							|  |  |  |           replace them with the contents of this backup. <b> This action cannot be undone - use with caution. </b> If | 
					
						
							|  |  |  |           the restoration is successful, you will be logged out. | 
					
						
							| 
									
										
										
										
											2021-08-21 00:46:43 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-13 15:42:22 -08:00
										 |  |  |           <v-checkbox | 
					
						
							|  |  |  |             v-model="confirmImport" | 
					
						
							|  |  |  |             class="checkbox-top" | 
					
						
							|  |  |  |             color="error" | 
					
						
							|  |  |  |             hide-details | 
					
						
							|  |  |  |             label="I understand that this action is irreversible, destructive and may cause data loss" | 
					
						
							|  |  |  |           ></v-checkbox> | 
					
						
							|  |  |  |         </v-card-text> | 
					
						
							|  |  |  |         <v-card-actions class="justify-center pt-0"> | 
					
						
							|  |  |  |           <BaseButton delete :disabled="!confirmImport" @click="restoreBackup(selected)"> | 
					
						
							|  |  |  |             <template #icon> {{ $globals.icons.database }} </template> | 
					
						
							|  |  |  |             Restore Backup | 
					
						
							|  |  |  |           </BaseButton> | 
					
						
							|  |  |  |         </v-card-actions> | 
					
						
							|  |  |  |         <p class="caption pb-0 mb-1 text-center"> | 
					
						
							|  |  |  |           {{ selected.name }} | 
					
						
							|  |  |  |         </p> | 
					
						
							| 
									
										
										
										
											2021-08-21 00:46:43 -08:00
										 |  |  |       </BaseDialog> | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-13 15:42:22 -08:00
										 |  |  |       <section> | 
					
						
							|  |  |  |         <BaseCardSectionTitle title="Backups"> | 
					
						
							|  |  |  |           <v-card-text class="py-0 px-1"> | 
					
						
							|  |  |  |             Backups a total snapshots of the database and data directory of the site. This includes all data and cannot | 
					
						
							|  |  |  |             be set to exclude subsets of data. You can think off this as a snapshot of Mealie at a specific time. | 
					
						
							|  |  |  |             Currently, this backup mechanism is not cross-version and therefore cannot be used to migrate data between | 
					
						
							|  |  |  |             versions (data migrations are not done automatically). These serve as a database agnostic way to export and | 
					
						
							|  |  |  |             import data or backup the site to an external location. | 
					
						
							| 
									
										
										
										
											2021-08-21 00:46:43 -08:00
										 |  |  |           </v-card-text> | 
					
						
							| 
									
										
										
										
											2022-03-13 15:42:22 -08:00
										 |  |  |         </BaseCardSectionTitle> | 
					
						
							|  |  |  |         <BaseButton @click="createBackup"> {{ $t("settings.backup.create-heading") }} </BaseButton> | 
					
						
							| 
									
										
										
										
											2021-08-21 00:46:43 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-04 14:18:46 -09:00
										 |  |  |         <v-data-table | 
					
						
							|  |  |  |           :headers="headers" | 
					
						
							|  |  |  |           :items="backups.imports || []" | 
					
						
							|  |  |  |           class="elevation-0" | 
					
						
							|  |  |  |           hide-default-footer | 
					
						
							|  |  |  |           disable-pagination | 
					
						
							|  |  |  |           :search="search" | 
					
						
							|  |  |  |           @click:row="setSelected" | 
					
						
							|  |  |  |         > | 
					
						
							|  |  |  |           <template #item.date="{ item }"> | 
					
						
							|  |  |  |             {{ $d(Date.parse(item.date), "medium") }} | 
					
						
							|  |  |  |           </template> | 
					
						
							|  |  |  |           <template #item.actions="{ item }"> | 
					
						
							|  |  |  |             <v-btn | 
					
						
							|  |  |  |               icon | 
					
						
							|  |  |  |               class="mx-1" | 
					
						
							|  |  |  |               color="error" | 
					
						
							|  |  |  |               @click.stop=" | 
					
						
							|  |  |  |                 deleteDialog = true; | 
					
						
							|  |  |  |                 deleteTarget = item.name; | 
					
						
							|  |  |  |               " | 
					
						
							|  |  |  |             > | 
					
						
							|  |  |  |               <v-icon> {{ $globals.icons.delete }} </v-icon> | 
					
						
							|  |  |  |             </v-btn> | 
					
						
							|  |  |  |             <BaseButton small download :download-url="backupsFileNameDownload(item.name)" @click.stop /> | 
					
						
							|  |  |  |           </template> | 
					
						
							|  |  |  |         </v-data-table> | 
					
						
							|  |  |  |         <v-divider></v-divider> | 
					
						
							|  |  |  |         <div class="d-flex justify-end mt-6"> | 
					
						
							|  |  |  |           <div> | 
					
						
							|  |  |  |             <AppButtonUpload | 
					
						
							|  |  |  |               :text-btn="false" | 
					
						
							|  |  |  |               class="mr-4" | 
					
						
							| 
									
										
										
										
											2022-03-13 15:42:22 -08:00
										 |  |  |               url="/api/admin/backups/upload" | 
					
						
							| 
									
										
										
										
											2021-12-04 14:18:46 -09:00
										 |  |  |               accept=".zip" | 
					
						
							|  |  |  |               color="info" | 
					
						
							|  |  |  |               @uploaded="refreshBackups()" | 
					
						
							|  |  |  |             /> | 
					
						
							|  |  |  |           </div> | 
					
						
							|  |  |  |         </div> | 
					
						
							|  |  |  |       </section> | 
					
						
							| 
									
										
										
										
											2021-08-21 00:46:43 -08:00
										 |  |  |     </section> | 
					
						
							| 
									
										
										
										
											2022-03-13 15:42:22 -08:00
										 |  |  |     <v-container class="mt-4 d-flex justify-end"> | 
					
						
							| 
									
										
										
										
											2022-04-09 19:08:48 -08:00
										 |  |  |       <v-btn outlined rounded to="/group/migrations"> Looking For Migrations? </v-btn> | 
					
						
							| 
									
										
										
										
											2022-03-13 15:42:22 -08:00
										 |  |  |     </v-container> | 
					
						
							| 
									
										
										
										
											2021-08-21 00:46:43 -08:00
										 |  |  |   </v-container> | 
					
						
							|  |  |  | </template> | 
					
						
							| 
									
										
										
										
											2021-08-21 11:00:42 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-21 00:46:43 -08:00
										 |  |  | <script lang="ts"> | 
					
						
							| 
									
										
										
										
											2022-03-13 15:42:22 -08:00
										 |  |  | import { defineComponent, reactive, ref, toRefs, useContext } from "@nuxtjs/composition-api"; | 
					
						
							|  |  |  | import { onMounted } from "vue-demi"; | 
					
						
							|  |  |  | import { useAdminApi } from "~/composables/api"; | 
					
						
							|  |  |  | import { AllBackups } from "~/types/api-types/admin"; | 
					
						
							| 
									
										
										
										
											2021-08-21 00:46:43 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  | export default defineComponent({ | 
					
						
							|  |  |  |   layout: "admin", | 
					
						
							|  |  |  |   setup() { | 
					
						
							| 
									
										
										
										
											2022-03-13 15:42:22 -08:00
										 |  |  |     const { i18n, $auth } = useContext(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     const adminApi = useAdminApi(); | 
					
						
							|  |  |  |     const selected = ref(""); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     const backups = ref<AllBackups>({ | 
					
						
							|  |  |  |       imports: [], | 
					
						
							|  |  |  |       templates: [], | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     async function refreshBackups() { | 
					
						
							|  |  |  |       const { data } = await adminApi.backups.getAll(); | 
					
						
							|  |  |  |       if (data) { | 
					
						
							|  |  |  |         backups.value = data; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     async function createBackup() { | 
					
						
							|  |  |  |       const { data } = await adminApi.backups.create(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       if (!data?.error) { | 
					
						
							|  |  |  |         refreshBackups(); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     async function restoreBackup(fileName: string) { | 
					
						
							|  |  |  |       const { data } = await adminApi.backups.restore(fileName); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       if (!data?.error) { | 
					
						
							|  |  |  |         $auth.logout(); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     const deleteTarget = ref(""); | 
					
						
							| 
									
										
										
										
											2021-08-21 00:46:43 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-13 15:42:22 -08:00
										 |  |  |     async function deleteBackup() { | 
					
						
							|  |  |  |       const { data } = await adminApi.backups.delete(deleteTarget.value); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       if (!data?.error) { | 
					
						
							|  |  |  |         refreshBackups(); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-08-21 00:46:43 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     const state = reactive({ | 
					
						
							| 
									
										
										
										
											2022-03-13 15:42:22 -08:00
										 |  |  |       confirmImport: false, | 
					
						
							| 
									
										
										
										
											2021-11-25 14:17:02 -09:00
										 |  |  |       deleteDialog: false, | 
					
						
							|  |  |  |       createDialog: false, | 
					
						
							|  |  |  |       importDialog: false, | 
					
						
							| 
									
										
										
										
											2021-08-21 00:46:43 -08:00
										 |  |  |       search: "", | 
					
						
							|  |  |  |       headers: [ | 
					
						
							|  |  |  |         { text: i18n.t("general.name"), value: "name" }, | 
					
						
							|  |  |  |         { text: i18n.t("general.created"), value: "date" }, | 
					
						
							| 
									
										
										
										
											2021-11-23 18:57:24 -09:00
										 |  |  |         { text: "Size", value: "size" }, | 
					
						
							| 
									
										
										
										
											2021-08-21 00:46:43 -08:00
										 |  |  |         { text: "", value: "actions", align: "right" }, | 
					
						
							|  |  |  |       ], | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     function setSelected(data: { name: string; date: string }) { | 
					
						
							|  |  |  |       if (selected.value === null || selected.value === undefined) { | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |       } | 
					
						
							| 
									
										
										
										
											2022-03-13 15:42:22 -08:00
										 |  |  |       selected.value = data.name; | 
					
						
							| 
									
										
										
										
											2021-11-25 14:17:02 -09:00
										 |  |  |       state.importDialog = true; | 
					
						
							| 
									
										
										
										
											2021-08-21 00:46:43 -08:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-13 15:42:22 -08:00
										 |  |  |     const backupsFileNameDownload = (fileName: string) => `api/admin/backups/${fileName}`; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     onMounted(refreshBackups); | 
					
						
							| 
									
										
										
										
											2021-08-21 00:46:43 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     return { | 
					
						
							| 
									
										
										
										
											2022-03-13 15:42:22 -08:00
										 |  |  |       restoreBackup, | 
					
						
							| 
									
										
										
										
											2021-08-21 00:46:43 -08:00
										 |  |  |       selected, | 
					
						
							|  |  |  |       ...toRefs(state), | 
					
						
							|  |  |  |       backups, | 
					
						
							|  |  |  |       createBackup, | 
					
						
							|  |  |  |       deleteBackup, | 
					
						
							|  |  |  |       deleteTarget, | 
					
						
							| 
									
										
										
										
											2022-03-13 15:42:22 -08:00
										 |  |  |       setSelected, | 
					
						
							| 
									
										
										
										
											2021-08-21 00:46:43 -08:00
										 |  |  |       refreshBackups, | 
					
						
							|  |  |  |       backupsFileNameDownload, | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  |   }, | 
					
						
							| 
									
										
										
										
											2021-10-07 09:39:47 -08:00
										 |  |  |   head() { | 
					
						
							|  |  |  |     return { | 
					
						
							|  |  |  |       title: this.$t("sidebar.backups") as string, | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  |   }, | 
					
						
							| 
									
										
										
										
											2021-08-21 00:46:43 -08:00
										 |  |  | }); | 
					
						
							|  |  |  | </script> | 
					
						
							| 
									
										
										
										
											2022-03-13 15:42:22 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  | <style> | 
					
						
							|  |  |  | .v-input--selection-controls__input { | 
					
						
							|  |  |  |   margin-bottom: auto; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | </style> |