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 @@
{{ $t("settings.site-settings") }}
+
+
+
+ Use this information to report a bug. Providing details of your instance to developers is the best way to get
+ your issues resolved quickly.
+
+
+
+
+ {{ $globals.icons.github }}
+ Tracker
+
+
+
+
+
+
+
+
+ {{ $globals.icons.github }}
+ Bug Report
+
+
+
+
+
-
-
- {{ property.icon || $globals.icons.user }}
-
-
-
- {{ property.name }}
-
-
- {{ property.value }}
-
-
-
+
+
+
+ {{ property.icon || $globals.icons.user }}
+
+
+
+ {{ property.name }}
+
+
+
+
+ {{ property.value }}
+
+
+
+
+
+ {{ 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):