diff --git a/frontend/components/Domain/Recipe/RecipeContextMenu.vue b/frontend/components/Domain/Recipe/RecipeContextMenu.vue index 4509479aa719..21df0ea245f7 100644 --- a/frontend/components/Domain/Recipe/RecipeContextMenu.vue +++ b/frontend/components/Domain/Recipe/RecipeContextMenu.vue @@ -97,6 +97,7 @@ import { useUserApi } from "~/composables/api"; import { alert } from "~/composables/use-toast"; import { MealType, planTypeOptions } from "~/composables/use-group-mealplan"; import { ShoppingListSummary } from "~/types/api-types/group"; +import { useAxiosDownloader } from "~/composables/api/use-axios-download"; export interface ContextMenuIncludes { delete: boolean; @@ -278,11 +279,13 @@ export default defineComponent({ context.emit("delete", props.slug); } + const download = useAxiosDownloader(); + async function handleDownloadEvent() { const { data } = await api.recipes.getZipToken(props.slug); if (data) { - window.open(api.recipes.getZipRedirectUrl(props.slug, data.token)); + download(api.recipes.getZipRedirectUrl(props.slug, data.token), `${props.slug}.zip`); } } diff --git a/frontend/composables/api/use-axios-download.ts b/frontend/composables/api/use-axios-download.ts new file mode 100644 index 000000000000..1dcb0ae01478 --- /dev/null +++ b/frontend/composables/api/use-axios-download.ts @@ -0,0 +1,22 @@ +import { useContext } from "@nuxtjs/composition-api"; + +export function useAxiosDownloader() { + const { $axios } = useContext(); + + function download(url: string, filename: string) { + $axios({ + url, + method: "GET", + responseType: "blob", + }).then((response) => { + const url = window.URL.createObjectURL(new Blob([response.data])); + const link = document.createElement("a"); + link.href = url; + link.setAttribute("download", filename); + document.body.appendChild(link); + link.click(); + }); + } + + return download; +} diff --git a/frontend/pages/admin/site-settings.vue b/frontend/pages/admin/site-settings.vue index 09be1651a875..0b369200f160 100644 --- a/frontend/pages/admin/site-settings.vue +++ b/frontend/pages/admin/site-settings.vue @@ -7,6 +7,36 @@ + + +
+ Use this information to report a bug. Providing details of your instance to developers is the best way to get + your issues resolved quickly. +
+ +
+ + + Tracker + + +
+
+
+ +
+ + + Bug Report + +
+
@@ -97,22 +127,39 @@
+ +
- - - {{ property.icon || $globals.icons.user }} - - - -
{{ property.name }}
-
- - {{ property.value }} - -
-
+
@@ -361,6 +408,12 @@ export default defineComponent({ icon: $globals.icons.group, value: data.defaultGroup, }, + { + slot: "recipe-scraper", + name: "Recipe Scraper Version", + icon: $globals.icons.primary, + value: data.recipeScraperVersion, + }, ]; return prettyInfo; @@ -374,7 +427,45 @@ export default defineComponent({ const appInfo = getAppInfo(); + const bugReportDialog = ref(false); + + const bugReportText = computed(() => { + const ignore = { + [i18n.tc("about.database-url")]: true, + [i18n.tc("about.default-group")]: true, + }; + let text = "**Details**\n"; + + appInfo.value?.forEach((item) => { + if (ignore[item.name as string]) { + return; + } + text += `${item.name as string}: ${item.value as string}\n`; + }); + + const ignoreChecks: { [key: string]: boolean } = { + "Application Version": true, + }; + + text += "\n**Checks**\n"; + + simpleChecks.value.forEach((item) => { + if (ignoreChecks[item.text]) { + return; + } + const status = item.status ? "Yes" : "No"; + text += `${item.text}: ${status}\n`; + }); + + text += `Email Configured: ${appConfig.value.emailReady ? "Yes" : "No"}\n`; + text += `Docker Volumes: ${docker.state}`; + + return text; + }); + return { + bugReportDialog, + bugReportText, DockerVolumeState, docker, dockerValidate, diff --git a/frontend/types/api-types/admin.ts b/frontend/types/api-types/admin.ts index e23b9c343145..9b00e3d161b0 100644 --- a/frontend/types/api-types/admin.ts +++ b/frontend/types/api-types/admin.ts @@ -17,6 +17,7 @@ export interface AdminAboutInfo { dbUrl?: string; defaultGroup: string; buildId: string; + recipeScraperVersion: string; } export interface AllBackups { imports: BackupFile[]; diff --git a/mealie/routes/admin/admin_about.py b/mealie/routes/admin/admin_about.py index 456179503b28..3972455102ad 100644 --- a/mealie/routes/admin/admin_about.py +++ b/mealie/routes/admin/admin_about.py @@ -4,6 +4,7 @@ import shutil import string from fastapi import APIRouter, BackgroundTasks +from recipe_scrapers import __version__ as recipe_scraper_version from mealie.core.release_checker import get_latest_version from mealie.core.settings.static import APP_VERSION @@ -33,6 +34,7 @@ class AdminAboutController(BaseAdminController): default_group=settings.DEFAULT_GROUP, allow_signup=settings.ALLOW_SIGNUP, build_id=settings.GIT_COMMIT_HASH, + recipe_scraper_version=recipe_scraper_version.__version__, ) @router.get("/statistics", response_model=AppStatistics) diff --git a/mealie/schema/admin/about.py b/mealie/schema/admin/about.py index 196faf4751ea..edaeb71dfdff 100644 --- a/mealie/schema/admin/about.py +++ b/mealie/schema/admin/about.py @@ -24,6 +24,7 @@ class AdminAboutInfo(AppInfo): db_url: str | None default_group: str build_id: str + recipe_scraper_version: str class CheckAppConfig(MealieModel):