mirror of
https://github.com/mealie-recipes/mealie.git
synced 2026-07-18 05:30:18 -04:00
feat: Added sitewide statistics (#7322)
This commit is contained in:
committed by
GitHub
parent
16a0ba2e21
commit
31187b1a74
@@ -940,7 +940,10 @@
|
||||
"openai-ready": "OpenAI Ready",
|
||||
"openai-not-ready": "OpenAI Not Ready",
|
||||
"openai-ready-error-text": "Not all OpenAI Values are configured. This can be ignored if you are not using OpenAI features.",
|
||||
"openai-ready-success-text": "Required OpenAI variables are all set."
|
||||
"openai-ready-success-text": "Required OpenAI variables are all set.",
|
||||
"site-statistics": "Site Statistics",
|
||||
"uncategorized-recipes": "Uncategorized Recipes",
|
||||
"untagged-recipes": "Untagged Recipes"
|
||||
},
|
||||
"shopping-list": {
|
||||
"all-lists": "All Lists",
|
||||
|
||||
@@ -157,6 +157,34 @@
|
||||
</v-alert>
|
||||
</section>
|
||||
|
||||
<!-- Site Statistics -->
|
||||
<section>
|
||||
<BaseCardSectionTitle
|
||||
class="pt-2"
|
||||
:icon="$globals.icons.chart"
|
||||
:title="$t('settings.site-statistics')"
|
||||
/>
|
||||
<div
|
||||
class="d-flex flex-wrap justify-center align-center"
|
||||
style="gap: 0.8rem"
|
||||
>
|
||||
<StatsCards
|
||||
v-for="(value, key) in adminStats"
|
||||
:key="`${key}-${value}`"
|
||||
:min-width="$vuetify.display.xs ? '100%' : '158'"
|
||||
:icon="getAdminStatsIcon(key)"
|
||||
:to="getAdminStatsTo(key)"
|
||||
>
|
||||
<template #title>
|
||||
{{ getAdminStatsTitle(key) }}
|
||||
</template>
|
||||
<template #value>
|
||||
{{ value }}
|
||||
</template>
|
||||
</StatsCards>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- General App Info -->
|
||||
<section class="mt-4">
|
||||
<BaseCardSectionTitle
|
||||
@@ -234,7 +262,8 @@ import type { TranslateResult } from "vue-i18n";
|
||||
import { useAdminApi, useUserApi } from "~/composables/api";
|
||||
import { validators } from "~/composables/use-validators";
|
||||
import { useAsyncKey } from "~/composables/use-utils";
|
||||
import type { CheckAppConfig } from "~/lib/api/types/admin";
|
||||
import StatsCards from "~/components/global/StatsCards.vue";
|
||||
import type { AppStatistics, CheckAppConfig } from "~/lib/api/types/admin";
|
||||
import AppLoader from "~/components/global/AppLoader.vue";
|
||||
|
||||
interface SimpleCheck {
|
||||
@@ -285,17 +314,68 @@ const appConfig = ref<CheckApp>({
|
||||
ldapReady: false,
|
||||
oidcReady: false,
|
||||
});
|
||||
const adminStats = ref<AppStatistics>({
|
||||
totalRecipes: 0,
|
||||
totalUsers: 0,
|
||||
totalHouseholds: 0,
|
||||
totalGroups: 0,
|
||||
uncategorizedRecipes: 0,
|
||||
untaggedRecipes: 0,
|
||||
});
|
||||
function isLocalHostOrHttps() {
|
||||
return window.location.hostname === "localhost" || window.location.protocol === "https:";
|
||||
}
|
||||
const api = useUserApi();
|
||||
const adminApi = useAdminApi();
|
||||
|
||||
const adminStatsText: { [key: string]: string } = {
|
||||
totalRecipes: i18n.t("general.recipes"),
|
||||
totalUsers: i18n.t("user.users"),
|
||||
totalHouseholds: i18n.t("household.households"),
|
||||
totalGroups: i18n.t("group.groups"),
|
||||
uncategorizedRecipes: i18n.t("settings.uncategorized-recipes"),
|
||||
untaggedRecipes: i18n.t("settings.untagged-recipes"),
|
||||
};
|
||||
|
||||
function getAdminStatsTitle(key: string) {
|
||||
return adminStatsText[key] ?? key;
|
||||
}
|
||||
|
||||
const adminStatsIcon: { [key: string]: string } = {
|
||||
totalRecipes: $globals.icons.primary,
|
||||
totalUsers: $globals.icons.user,
|
||||
totalHouseholds: $globals.icons.household,
|
||||
totalGroups: $globals.icons.group,
|
||||
uncategorizedRecipes: $globals.icons.categories,
|
||||
untaggedRecipes: $globals.icons.tags,
|
||||
};
|
||||
|
||||
function getAdminStatsIcon(key: string) {
|
||||
return adminStatsIcon[key] ?? $globals.icons.primary;
|
||||
}
|
||||
|
||||
const adminStatsTo = computed<{ [key: string]: string }>(() => {
|
||||
return {
|
||||
totalUsers: "/admin/manage/users",
|
||||
totalHouseholds: "/admin/manage/households",
|
||||
totalGroups: "/admin/manage/groups",
|
||||
};
|
||||
});
|
||||
|
||||
function getAdminStatsTo(key: string) {
|
||||
return adminStatsTo.value[key] ?? undefined;
|
||||
}
|
||||
|
||||
onMounted(async () => {
|
||||
const { data } = await adminApi.about.checkApp();
|
||||
if (data) {
|
||||
appConfig.value = { ...data, isSiteSecure: false };
|
||||
}
|
||||
appConfig.value.isSiteSecure = isLocalHostOrHttps();
|
||||
const { data: adminData } = await adminApi.about.statistics();
|
||||
if (adminData) {
|
||||
adminStats.value = adminData;
|
||||
}
|
||||
});
|
||||
const simpleChecks = computed<SimpleCheck[]>(() => {
|
||||
const goodIcon = $globals.icons.checkboxMarkedCircle;
|
||||
|
||||
Reference in New Issue
Block a user