mirror of
https://github.com/hay-kot/mealie.git
synced 2025-08-22 14:33:33 -07:00
Site Pages Import/Export
This commit is contained in:
parent
81c74d407f
commit
ddad451489
7 changed files with 64 additions and 47 deletions
|
@ -26,6 +26,10 @@ export default {
|
||||||
value: true,
|
value: true,
|
||||||
text: this.$t("general.settings"),
|
text: this.$t("general.settings"),
|
||||||
},
|
},
|
||||||
|
pages: {
|
||||||
|
value: true,
|
||||||
|
text: "Pages",
|
||||||
|
},
|
||||||
themes: {
|
themes: {
|
||||||
value: true,
|
value: true,
|
||||||
text: this.$t("general.themes"),
|
text: this.$t("general.themes"),
|
||||||
|
@ -50,6 +54,7 @@ export default {
|
||||||
recipes: this.options.recipes.value,
|
recipes: this.options.recipes.value,
|
||||||
settings: this.options.settings.value,
|
settings: this.options.settings.value,
|
||||||
themes: this.options.themes.value,
|
themes: this.options.themes.value,
|
||||||
|
pages: this.options.pages.value,
|
||||||
users: this.options.users.value,
|
users: this.options.users.value,
|
||||||
groups: this.options.groups.value,
|
groups: this.options.groups.value,
|
||||||
});
|
});
|
||||||
|
|
|
@ -28,38 +28,14 @@
|
||||||
<v-tab>{{ $t("general.recipes") }}</v-tab>
|
<v-tab>{{ $t("general.recipes") }}</v-tab>
|
||||||
<v-tab>{{ $t("general.themes") }}</v-tab>
|
<v-tab>{{ $t("general.themes") }}</v-tab>
|
||||||
<v-tab>{{ $t("general.settings") }}</v-tab>
|
<v-tab>{{ $t("general.settings") }}</v-tab>
|
||||||
|
<v-tab> Pages </v-tab>
|
||||||
<v-tab>{{ $t("general.users") }}</v-tab>
|
<v-tab>{{ $t("general.users") }}</v-tab>
|
||||||
<v-tab>{{ $t("general.groups") }}</v-tab>
|
<v-tab>{{ $t("general.groups") }}</v-tab>
|
||||||
</v-tabs>
|
</v-tabs>
|
||||||
<v-tabs-items v-model="tab">
|
<v-tabs-items v-model="tab">
|
||||||
<v-tab-item>
|
<v-tab-item v-for="(table, index) in allTables" :key="index">
|
||||||
<v-card flat>
|
<v-card flat>
|
||||||
<DataTable :data-headers="importHeaders" :data-set="recipeData" />
|
<DataTable :data-headers="importHeaders" :data-set="table" />
|
||||||
</v-card>
|
|
||||||
</v-tab-item>
|
|
||||||
<v-tab-item>
|
|
||||||
<v-card>
|
|
||||||
<DataTable
|
|
||||||
:data-headers="importHeaders"
|
|
||||||
:data-set="themeData"
|
|
||||||
/> </v-card
|
|
||||||
></v-tab-item>
|
|
||||||
<v-tab-item>
|
|
||||||
<v-card
|
|
||||||
><DataTable
|
|
||||||
:data-headers="importHeaders"
|
|
||||||
:data-set="settingsData"
|
|
||||||
/>
|
|
||||||
</v-card>
|
|
||||||
</v-tab-item>
|
|
||||||
<v-tab-item>
|
|
||||||
<v-card
|
|
||||||
><DataTable :data-headers="importHeaders" :data-set="userData" />
|
|
||||||
</v-card>
|
|
||||||
</v-tab-item>
|
|
||||||
<v-tab-item>
|
|
||||||
<v-card
|
|
||||||
><DataTable :data-headers="importHeaders" :data-set="groupData" />
|
|
||||||
</v-card>
|
</v-card>
|
||||||
</v-tab-item>
|
</v-tab-item>
|
||||||
</v-tabs-items>
|
</v-tabs-items>
|
||||||
|
@ -82,6 +58,7 @@ export default {
|
||||||
settingsData: [],
|
settingsData: [],
|
||||||
userData: [],
|
userData: [],
|
||||||
groupData: [],
|
groupData: [],
|
||||||
|
pageData: [],
|
||||||
importHeaders: [
|
importHeaders: [
|
||||||
{
|
{
|
||||||
text: "Status",
|
text: "Status",
|
||||||
|
@ -118,15 +95,29 @@ export default {
|
||||||
groupNumbers() {
|
groupNumbers() {
|
||||||
return this.calculateNumbers(this.$t("general.groups"), this.groupData);
|
return this.calculateNumbers(this.$t("general.groups"), this.groupData);
|
||||||
},
|
},
|
||||||
|
pageNumbers() {
|
||||||
|
return this.calculateNumbers("Pages", this.pageData);
|
||||||
|
},
|
||||||
allNumbers() {
|
allNumbers() {
|
||||||
return [
|
return [
|
||||||
this.recipeNumbers,
|
this.recipeNumbers,
|
||||||
this.settingsNumbers,
|
|
||||||
this.themeNumbers,
|
this.themeNumbers,
|
||||||
|
this.settingsNumbers,
|
||||||
|
this.pageNumbers,
|
||||||
this.userNumbers,
|
this.userNumbers,
|
||||||
this.groupNumbers,
|
this.groupNumbers,
|
||||||
];
|
];
|
||||||
},
|
},
|
||||||
|
allTables() {
|
||||||
|
return [
|
||||||
|
this.recipeData,
|
||||||
|
this.themeData,
|
||||||
|
this.settingsData,
|
||||||
|
this.pageData,
|
||||||
|
this.userData,
|
||||||
|
this.groupData,
|
||||||
|
];
|
||||||
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
|
@ -146,6 +137,7 @@ export default {
|
||||||
this.settingsData = importData.settingsImports;
|
this.settingsData = importData.settingsImports;
|
||||||
this.userData = importData.userImports;
|
this.userData = importData.userImports;
|
||||||
this.groupData = importData.groupImports;
|
this.groupData = importData.groupImports;
|
||||||
|
this.pageData = importData.pageImports;
|
||||||
this.dialog = true;
|
this.dialog = true;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
@ -18,14 +18,11 @@ router = APIRouter(prefix="/api/backups", tags=["Backups"])
|
||||||
def available_imports():
|
def available_imports():
|
||||||
"""Returns a list of avaiable .zip files for import into Mealie."""
|
"""Returns a list of avaiable .zip files for import into Mealie."""
|
||||||
imports = []
|
imports = []
|
||||||
templates = []
|
|
||||||
for archive in BACKUP_DIR.glob("*.zip"):
|
for archive in BACKUP_DIR.glob("*.zip"):
|
||||||
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("*.*"):
|
templates = [template.name for template in TEMPLATE_DIR.glob("*.*")]
|
||||||
templates.append(template.name)
|
|
||||||
|
|
||||||
imports.sort(key=operator.attrgetter("date"), reverse=True)
|
imports.sort(key=operator.attrgetter("date"), reverse=True)
|
||||||
|
|
||||||
return Imports(imports=imports, templates=templates)
|
return Imports(imports=imports, templates=templates)
|
||||||
|
@ -40,6 +37,7 @@ def export_database(data: BackupJob, session: Session = Depends(generate_session
|
||||||
templates=data.templates,
|
templates=data.templates,
|
||||||
export_recipes=data.options.recipes,
|
export_recipes=data.options.recipes,
|
||||||
export_settings=data.options.settings,
|
export_settings=data.options.settings,
|
||||||
|
export_pages=data.options.pages,
|
||||||
export_themes=data.options.themes,
|
export_themes=data.options.themes,
|
||||||
export_users=data.options.users,
|
export_users=data.options.users,
|
||||||
export_groups=data.options.groups,
|
export_groups=data.options.groups,
|
||||||
|
@ -82,11 +80,12 @@ async def upload_nextcloud_zipfile(file_name: str):
|
||||||
def import_database(file_name: str, import_data: ImportJob, session: Session = Depends(generate_session)):
|
def import_database(file_name: str, import_data: ImportJob, session: Session = Depends(generate_session)):
|
||||||
""" Import a database backup file generated from Mealie. """
|
""" Import a database backup file generated from Mealie. """
|
||||||
|
|
||||||
imported = imports.import_database(
|
return imports.import_database(
|
||||||
session=session,
|
session=session,
|
||||||
archive=import_data.name,
|
archive=import_data.name,
|
||||||
import_recipes=import_data.recipes,
|
import_recipes=import_data.recipes,
|
||||||
import_settings=import_data.settings,
|
import_settings=import_data.settings,
|
||||||
|
import_pages=import_data.pages,
|
||||||
import_themes=import_data.themes,
|
import_themes=import_data.themes,
|
||||||
import_users=import_data.users,
|
import_users=import_data.users,
|
||||||
import_groups=import_data.groups,
|
import_groups=import_data.groups,
|
||||||
|
@ -94,8 +93,6 @@ def import_database(file_name: str, import_data: ImportJob, session: Session = D
|
||||||
rebase=import_data.rebase,
|
rebase=import_data.rebase,
|
||||||
)
|
)
|
||||||
|
|
||||||
return imported
|
|
||||||
|
|
||||||
|
|
||||||
@router.delete("/{file_name}/delete", status_code=200)
|
@router.delete("/{file_name}/delete", status_code=200)
|
||||||
def delete_backup(file_name: str):
|
def delete_backup(file_name: str):
|
||||||
|
|
|
@ -7,6 +7,7 @@ from pydantic import BaseModel
|
||||||
class BackupOptions(BaseModel):
|
class BackupOptions(BaseModel):
|
||||||
recipes: bool = True
|
recipes: bool = True
|
||||||
settings: bool = True
|
settings: bool = True
|
||||||
|
pages: bool = True
|
||||||
themes: bool = True
|
themes: bool = True
|
||||||
groups: bool = True
|
groups: bool = True
|
||||||
users: bool = True
|
users: bool = True
|
||||||
|
|
|
@ -27,3 +27,7 @@ class GroupImport(ImportBase):
|
||||||
|
|
||||||
class UserImport(ImportBase):
|
class UserImport(ImportBase):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class CustomPageImport(ImportBase):
|
||||||
|
pass
|
||||||
|
|
|
@ -4,11 +4,11 @@ from datetime import datetime
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Union
|
from typing import Union
|
||||||
|
|
||||||
|
from fastapi.logger import logger
|
||||||
|
from jinja2 import Template
|
||||||
from mealie.core.config import BACKUP_DIR, IMG_DIR, TEMP_DIR, TEMPLATE_DIR
|
from mealie.core.config import BACKUP_DIR, IMG_DIR, TEMP_DIR, TEMPLATE_DIR
|
||||||
from mealie.db.database import db
|
from mealie.db.database import db
|
||||||
from mealie.db.db_setup import create_session
|
from mealie.db.db_setup import create_session
|
||||||
from fastapi.logger import logger
|
|
||||||
from jinja2 import Template
|
|
||||||
from pydantic.main import BaseModel
|
from pydantic.main import BaseModel
|
||||||
|
|
||||||
|
|
||||||
|
@ -101,6 +101,7 @@ def backup_all(
|
||||||
templates=None,
|
templates=None,
|
||||||
export_recipes=True,
|
export_recipes=True,
|
||||||
export_settings=True,
|
export_settings=True,
|
||||||
|
export_pages=True,
|
||||||
export_themes=True,
|
export_themes=True,
|
||||||
export_users=True,
|
export_users=True,
|
||||||
export_groups=True,
|
export_groups=True,
|
||||||
|
@ -125,6 +126,10 @@ def backup_all(
|
||||||
all_settings = db.settings.get_all(session)
|
all_settings = db.settings.get_all(session)
|
||||||
db_export.export_items(all_settings, "settings")
|
db_export.export_items(all_settings, "settings")
|
||||||
|
|
||||||
|
if export_pages:
|
||||||
|
all_pages = db.custom_pages.get_all(session)
|
||||||
|
db_export.export_items(all_pages, "pages")
|
||||||
|
|
||||||
if export_themes:
|
if export_themes:
|
||||||
all_themes = db.themes.get_all(session)
|
all_themes = db.themes.get_all(session)
|
||||||
db_export.export_items(all_themes, "themes")
|
db_export.export_items(all_themes, "themes")
|
||||||
|
@ -136,10 +141,7 @@ def auto_backup_job():
|
||||||
for backup in BACKUP_DIR.glob("Auto*.zip"):
|
for backup in BACKUP_DIR.glob("Auto*.zip"):
|
||||||
backup.unlink()
|
backup.unlink()
|
||||||
|
|
||||||
templates = []
|
templates = [template for template in TEMPLATE_DIR.iterdir()]
|
||||||
for template in TEMPLATE_DIR.iterdir():
|
|
||||||
templates.append(template)
|
|
||||||
|
|
||||||
session = create_session()
|
session = create_session()
|
||||||
backup_all(session=session, tag="Auto", templates=templates)
|
backup_all(session=session, tag="Auto", templates=templates)
|
||||||
logger.info("Auto Backup Called")
|
logger.info("Auto Backup Called")
|
||||||
|
|
|
@ -7,8 +7,8 @@ from typing import Callable, List
|
||||||
from mealie.core.config import BACKUP_DIR, IMG_DIR, TEMP_DIR
|
from mealie.core.config import BACKUP_DIR, IMG_DIR, TEMP_DIR
|
||||||
from mealie.db.database import db
|
from mealie.db.database import db
|
||||||
from mealie.schema.recipe import Recipe
|
from mealie.schema.recipe import Recipe
|
||||||
from mealie.schema.restore import GroupImport, RecipeImport, SettingsImport, ThemeImport, UserImport
|
from mealie.schema.restore import CustomPageImport, GroupImport, RecipeImport, SettingsImport, ThemeImport, UserImport
|
||||||
from mealie.schema.settings import SiteSettings
|
from mealie.schema.settings import CustomPageOut, SiteSettings
|
||||||
from mealie.schema.theme import SiteTheme
|
from mealie.schema.theme import SiteTheme
|
||||||
from mealie.schema.user import UpdateGroup, UserInDB
|
from mealie.schema.user import UpdateGroup, UserInDB
|
||||||
from pydantic.main import BaseModel
|
from pydantic.main import BaseModel
|
||||||
|
@ -42,7 +42,6 @@ class ImportDatabase:
|
||||||
|
|
||||||
with zipfile.ZipFile(self.archive, "r") as zip_ref:
|
with zipfile.ZipFile(self.archive, "r") as zip_ref:
|
||||||
zip_ref.extractall(self.import_dir)
|
zip_ref.extractall(self.import_dir)
|
||||||
pass
|
|
||||||
else:
|
else:
|
||||||
raise Exception("Import file does not exist")
|
raise Exception("Import file does not exist")
|
||||||
|
|
||||||
|
@ -95,9 +94,7 @@ class ImportDatabase:
|
||||||
|
|
||||||
try:
|
try:
|
||||||
if "" in recipe_dict["categories"]:
|
if "" in recipe_dict["categories"]:
|
||||||
recipe_dict["categories"] = [
|
recipe_dict["categories"] = [cat for cat in recipe_dict["categories"] if cat != ""]
|
||||||
cat for cat in recipe_dict["categories"] if cat != ""
|
|
||||||
]
|
|
||||||
|
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
|
@ -149,6 +146,19 @@ class ImportDatabase:
|
||||||
|
|
||||||
return [import_status]
|
return [import_status]
|
||||||
|
|
||||||
|
def import_pages(self):
|
||||||
|
pages_file = self.import_dir.joinpath("pages", "pages.json")
|
||||||
|
pages = ImportDatabase.read_models_file(pages_file, CustomPageOut)
|
||||||
|
|
||||||
|
page_imports = []
|
||||||
|
for page in pages:
|
||||||
|
import_stats = self.import_model(
|
||||||
|
db_table=db.custom_pages, model=page, return_model=CustomPageImport, name_attr="name", search_key="slug"
|
||||||
|
)
|
||||||
|
page_imports.append(import_stats)
|
||||||
|
|
||||||
|
return page_imports
|
||||||
|
|
||||||
def import_groups(self):
|
def import_groups(self):
|
||||||
groups_file = self.import_dir.joinpath("groups", "groups.json")
|
groups_file = self.import_dir.joinpath("groups", "groups.json")
|
||||||
groups = ImportDatabase.read_models_file(groups_file, UpdateGroup)
|
groups = ImportDatabase.read_models_file(groups_file, UpdateGroup)
|
||||||
|
@ -273,6 +283,7 @@ def import_database(
|
||||||
archive,
|
archive,
|
||||||
import_recipes=True,
|
import_recipes=True,
|
||||||
import_settings=True,
|
import_settings=True,
|
||||||
|
import_pages=True,
|
||||||
import_themes=True,
|
import_themes=True,
|
||||||
import_users=True,
|
import_users=True,
|
||||||
import_groups=True,
|
import_groups=True,
|
||||||
|
@ -293,6 +304,10 @@ def import_database(
|
||||||
if import_themes:
|
if import_themes:
|
||||||
theme_report = import_session.import_themes()
|
theme_report = import_session.import_themes()
|
||||||
|
|
||||||
|
if import_pages:
|
||||||
|
print("IMport Pages")
|
||||||
|
page_report = import_session.import_pages()
|
||||||
|
|
||||||
group_report = []
|
group_report = []
|
||||||
if import_groups:
|
if import_groups:
|
||||||
group_report = import_session.import_groups()
|
group_report = import_session.import_groups()
|
||||||
|
@ -307,6 +322,7 @@ def import_database(
|
||||||
"recipeImports": recipe_report,
|
"recipeImports": recipe_report,
|
||||||
"settingsImports": settings_report,
|
"settingsImports": settings_report,
|
||||||
"themeImports": theme_report,
|
"themeImports": theme_report,
|
||||||
|
"pageImports": page_report,
|
||||||
"groupImports": group_report,
|
"groupImports": group_report,
|
||||||
"userImports": user_report,
|
"userImports": user_report,
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue