mirror of
https://github.com/hay-kot/mealie.git
synced 2025-08-22 06:23:34 -07:00
backup card functionality
This commit is contained in:
parent
8c32fd9840
commit
b3982f8bfa
7 changed files with 127 additions and 52 deletions
|
@ -28,15 +28,8 @@ export default {
|
||||||
await apiReq.delete(backupURLs.deleteBackup(fileName));
|
await apiReq.delete(backupURLs.deleteBackup(fileName));
|
||||||
},
|
},
|
||||||
|
|
||||||
async create(tag, template) {
|
async create(data) {
|
||||||
if (typeof template == String) {
|
let response = apiReq.post(backupURLs.createBackup, data);
|
||||||
template = [template];
|
|
||||||
}
|
|
||||||
console.log(tag, template);
|
|
||||||
let response = apiReq.post(backupURLs.createBackup, {
|
|
||||||
tag: tag,
|
|
||||||
template: template,
|
|
||||||
});
|
|
||||||
return response;
|
return response;
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,8 +1,10 @@
|
||||||
<template>
|
<template>
|
||||||
<v-card :loading="loading">
|
<v-card :loading="loading">
|
||||||
<v-card-title> Create a Backup </v-card-title>
|
<v-card-title> Create a Backup </v-card-title>
|
||||||
|
<v-card-text class="mt-n3">
|
||||||
<v-card-actions class="mt-n6">
|
<v-text-field dense label="Backup Tag" v-model="tag"></v-text-field>
|
||||||
|
</v-card-text>
|
||||||
|
<v-card-actions class="mt-n9">
|
||||||
<v-switch v-model="fullBackup" :label="switchLabel"></v-switch>
|
<v-switch v-model="fullBackup" :label="switchLabel"></v-switch>
|
||||||
<v-spacer></v-spacer>
|
<v-spacer></v-spacer>
|
||||||
<v-btn color="success" text @click="createBackup()"> Create </v-btn>
|
<v-btn color="success" text @click="createBackup()"> Create </v-btn>
|
||||||
|
@ -13,31 +15,23 @@
|
||||||
<v-col sm="4">
|
<v-col sm="4">
|
||||||
<p>Options:</p>
|
<p>Options:</p>
|
||||||
<v-checkbox
|
<v-checkbox
|
||||||
|
v-for="option in options"
|
||||||
|
:key="option.text"
|
||||||
class="mb-n4 mt-n3"
|
class="mb-n4 mt-n3"
|
||||||
dense
|
dense
|
||||||
label="Recipes"
|
:label="option.text"
|
||||||
v-model="importRecipes"
|
v-model="option.value"
|
||||||
></v-checkbox>
|
|
||||||
<v-checkbox
|
|
||||||
class="my-n4"
|
|
||||||
dense
|
|
||||||
label="Themes"
|
|
||||||
v-model="importThemes"
|
|
||||||
></v-checkbox>
|
|
||||||
<v-checkbox
|
|
||||||
class="my-n4"
|
|
||||||
dense
|
|
||||||
label="Settings"
|
|
||||||
v-model="importThemes"
|
|
||||||
></v-checkbox>
|
></v-checkbox>
|
||||||
</v-col>
|
</v-col>
|
||||||
<v-col>
|
<v-col>
|
||||||
<p>Templates:</p>
|
<p>Templates:</p>
|
||||||
<v-checkbox
|
<v-checkbox
|
||||||
|
v-for="template in availableTemplates"
|
||||||
|
:key="template"
|
||||||
class="mb-n4 mt-n3"
|
class="mb-n4 mt-n3"
|
||||||
dense
|
dense
|
||||||
label="Template asdfasdf"
|
:label="template"
|
||||||
v-model="importRecipes"
|
@click="appendTemplate(template)"
|
||||||
></v-checkbox>
|
></v-checkbox>
|
||||||
</v-col>
|
</v-col>
|
||||||
</v-row>
|
</v-row>
|
||||||
|
@ -46,13 +40,34 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
import api from "../../../api";
|
||||||
export default {
|
export default {
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
|
tag: null,
|
||||||
fullBackup: true,
|
fullBackup: true,
|
||||||
loading: false,
|
loading: false,
|
||||||
|
options: {
|
||||||
|
recipes: {
|
||||||
|
value: true,
|
||||||
|
text: "Recipes",
|
||||||
|
},
|
||||||
|
settings: {
|
||||||
|
value: true,
|
||||||
|
text: "Settings",
|
||||||
|
},
|
||||||
|
themes: {
|
||||||
|
value: true,
|
||||||
|
text: "Themes",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
availableTemplates: [],
|
||||||
|
selectedTemplates: [],
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
mounted() {
|
||||||
|
this.getAvailableBackups();
|
||||||
|
},
|
||||||
computed: {
|
computed: {
|
||||||
switchLabel() {
|
switchLabel() {
|
||||||
if (this.fullBackup) {
|
if (this.fullBackup) {
|
||||||
|
@ -61,8 +76,39 @@ export default {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
createBackup() {
|
async getAvailableBackups() {
|
||||||
|
let response = await api.backups.requestAvailable();
|
||||||
|
response.templates.forEach((element) => {
|
||||||
|
this.availableTemplates.push(element);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
async createBackup() {
|
||||||
this.loading = true;
|
this.loading = true;
|
||||||
|
|
||||||
|
let data = {
|
||||||
|
tag: this.tag,
|
||||||
|
options: {
|
||||||
|
recipes: this.options.recipes.value,
|
||||||
|
settings: this.options.settings.value,
|
||||||
|
themes: this.options.themes.value,
|
||||||
|
},
|
||||||
|
templates: this.selectedTemplates,
|
||||||
|
};
|
||||||
|
|
||||||
|
console.log(data);
|
||||||
|
|
||||||
|
await api.backups.create(data);
|
||||||
|
this.loading = false;
|
||||||
|
|
||||||
|
this.$emit("created");
|
||||||
|
},
|
||||||
|
appendTemplate(templateName) {
|
||||||
|
if (this.selectedTemplates.includes(templateName)) {
|
||||||
|
let index = this.selectedTemplates.indexOf(templateName);
|
||||||
|
if (index !== -1) {
|
||||||
|
this.selectedTemplates.splice(index, 1);
|
||||||
|
}
|
||||||
|
} else this.selectedTemplates.push(templateName);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
<v-card-text>
|
<v-card-text>
|
||||||
<v-row>
|
<v-row>
|
||||||
<v-col cols="12" md="6" ss="12">
|
<v-col cols="12" md="6" ss="12">
|
||||||
<NewBackupCard />
|
<NewBackupCard @created="processFinished" />
|
||||||
</v-col>
|
</v-col>
|
||||||
<v-col cols="12" md="6" sm="12">
|
<v-col cols="12" md="6" sm="12">
|
||||||
<p>
|
<p>
|
||||||
|
@ -16,6 +16,8 @@
|
||||||
</p>
|
</p>
|
||||||
</v-col>
|
</v-col>
|
||||||
</v-row>
|
</v-row>
|
||||||
|
<v-divider class="mb-3"></v-divider>
|
||||||
|
|
||||||
<AvailableBackupCard
|
<AvailableBackupCard
|
||||||
@loading="backupLoading = true"
|
@loading="backupLoading = true"
|
||||||
@finished="processFinished"
|
@finished="processFinished"
|
||||||
|
|
|
@ -56,8 +56,8 @@ app.include_router(static_routes.router)
|
||||||
# post_start()
|
# post_start()
|
||||||
|
|
||||||
# Generate API Documentation
|
# Generate API Documentation
|
||||||
if not PRODUCTION:
|
# if not PRODUCTION:
|
||||||
generate_api_docs(app)
|
# generate_api_docs(app)
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
logger.info("-----SYSTEM STARTUP-----")
|
logger.info("-----SYSTEM STARTUP-----")
|
||||||
|
|
|
@ -4,15 +4,32 @@ from typing import List, Optional
|
||||||
from pydantic import BaseModel
|
from pydantic import BaseModel
|
||||||
|
|
||||||
|
|
||||||
|
class BackupOptions(BaseModel):
|
||||||
|
recipes: bool = True
|
||||||
|
settings: bool = True
|
||||||
|
themes: bool = True
|
||||||
|
|
||||||
|
class Config:
|
||||||
|
schema_extra = {
|
||||||
|
"example": {
|
||||||
|
"recipes": True,
|
||||||
|
"settings": True,
|
||||||
|
"themes": True,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
class BackupJob(BaseModel):
|
class BackupJob(BaseModel):
|
||||||
tag: Optional[str]
|
tag: Optional[str]
|
||||||
template: Optional[List[str]]
|
options: BackupOptions
|
||||||
|
templates: Optional[List[str]] = []
|
||||||
|
|
||||||
class Config:
|
class Config:
|
||||||
schema_extra = {
|
schema_extra = {
|
||||||
"example": {
|
"example": {
|
||||||
"tag": "July 23rd 2021",
|
"tag": "July 23rd 2021",
|
||||||
"template": "recipes.md",
|
"options": BackupOptions,
|
||||||
|
"template": ["recipes.md"],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -49,13 +66,13 @@ class ImportJob(BaseModel):
|
||||||
settings: bool = False
|
settings: bool = False
|
||||||
|
|
||||||
class Config:
|
class Config:
|
||||||
schema_extra = {
|
schema_extra = {
|
||||||
"example": {
|
"example": {
|
||||||
"name": "my_local_backup.zip",
|
"name": "my_local_backup.zip",
|
||||||
"recipes": True,
|
"recipes": True,
|
||||||
"force": False,
|
"force": False,
|
||||||
"rebase": False,
|
"rebase": False,
|
||||||
"themes": False,
|
"themes": False,
|
||||||
"settings": False
|
"settings": False,
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -19,7 +19,7 @@ def available_imports():
|
||||||
backup = LocalBackup(name=archive.name, date=archive.stat().st_ctime)
|
backup = LocalBackup(name=archive.name, date=archive.stat().st_ctime)
|
||||||
imports.append(backup)
|
imports.append(backup)
|
||||||
|
|
||||||
for template in TEMPLATE_DIR.glob("*.md"):
|
for template in TEMPLATE_DIR.glob("*.*"):
|
||||||
templates.append(template.name)
|
templates.append(template.name)
|
||||||
|
|
||||||
imports.sort(key=operator.attrgetter("date"), reverse=True)
|
imports.sort(key=operator.attrgetter("date"), reverse=True)
|
||||||
|
@ -30,7 +30,13 @@ def available_imports():
|
||||||
@router.post("/api/backups/export/database/", status_code=201)
|
@router.post("/api/backups/export/database/", status_code=201)
|
||||||
def export_database(data: BackupJob):
|
def export_database(data: BackupJob):
|
||||||
"""Generates a backup of the recipe database in json format."""
|
"""Generates a backup of the recipe database in json format."""
|
||||||
export_path = backup_all(data.tag, data.template)
|
export_path = backup_all(
|
||||||
|
tag=data.tag,
|
||||||
|
templates=data.templates,
|
||||||
|
export_recipes=data.options.recipes,
|
||||||
|
export_settings=data.options.settings,
|
||||||
|
export_themes=data.options.themes,
|
||||||
|
)
|
||||||
try:
|
try:
|
||||||
return SnackResponse.success("Backup Created at " + export_path)
|
return SnackResponse.success("Backup Created at " + export_path)
|
||||||
except:
|
except:
|
||||||
|
|
|
@ -3,11 +3,11 @@ import shutil
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
|
from app_config import BACKUP_DIR, IMG_DIR, TEMP_DIR, TEMPLATE_DIR
|
||||||
from jinja2 import Template
|
from jinja2 import Template
|
||||||
from services.meal_services import MealPlan
|
from services.meal_services import MealPlan
|
||||||
from services.recipe_services import Recipe
|
from services.recipe_services import Recipe
|
||||||
from services.settings_services import SiteSettings, SiteTheme
|
from services.settings_services import SiteSettings, SiteTheme
|
||||||
from app_config import BACKUP_DIR, IMG_DIR, TEMP_DIR, TEMPLATE_DIR
|
|
||||||
from utils.logger import logger
|
from utils.logger import logger
|
||||||
|
|
||||||
|
|
||||||
|
@ -123,15 +123,26 @@ class ExportDatabase:
|
||||||
return str(zip_path.absolute()) + ".zip"
|
return str(zip_path.absolute()) + ".zip"
|
||||||
|
|
||||||
|
|
||||||
def backup_all(tag=None, templates=None):
|
def backup_all(
|
||||||
|
tag=None,
|
||||||
|
templates=None,
|
||||||
|
export_recipes=True,
|
||||||
|
export_settings=True,
|
||||||
|
export_themes=True,
|
||||||
|
):
|
||||||
db_export = ExportDatabase(tag=tag, templates=templates)
|
db_export = ExportDatabase(tag=tag, templates=templates)
|
||||||
|
|
||||||
db_export.export_recipes()
|
if export_recipes:
|
||||||
db_export.export_images()
|
db_export.export_recipes()
|
||||||
db_export.export_settings()
|
db_export.export_images()
|
||||||
db_export.export_themes()
|
|
||||||
db_export.export_meals()
|
if export_settings:
|
||||||
#
|
db_export.export_settings()
|
||||||
|
|
||||||
|
if export_themes:
|
||||||
|
db_export.export_themes()
|
||||||
|
# db_export.export_meals()
|
||||||
|
|
||||||
return db_export.finish_export()
|
return db_export.finish_export()
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue