mirror of
https://github.com/mealie-recipes/mealie.git
synced 2025-07-24 23:59:45 +02:00
feat: Show Cookbooks from Other Households (#4452)
This commit is contained in:
parent
8983745106
commit
87f4b23711
13 changed files with 264 additions and 55 deletions
|
@ -82,12 +82,17 @@ import { computed, defineComponent, onMounted, ref, useContext, useRoute } from
|
|||
import { useLoggedInState } from "~/composables/use-logged-in-state";
|
||||
import AppHeader from "@/components/Layout/LayoutParts/AppHeader.vue";
|
||||
import AppSidebar from "@/components/Layout/LayoutParts/AppSidebar.vue";
|
||||
import { SidebarLinks } from "~/types/application-types";
|
||||
import { SideBarLink } from "~/types/application-types";
|
||||
import LanguageDialog from "~/components/global/LanguageDialog.vue";
|
||||
import TheSnackbar from "@/components/Layout/LayoutParts/TheSnackbar.vue";
|
||||
import { useAppInfo } from "~/composables/api";
|
||||
import { useCookbooks, usePublicCookbooks } from "~/composables/use-group-cookbooks";
|
||||
import { useCookbookPreferences } from "~/composables/use-users/preferences";
|
||||
import { useHouseholdStore, usePublicHouseholdStore } from "~/composables/store/use-household-store";
|
||||
import { useToggleDarkMode } from "~/composables/use-utils";
|
||||
import { ReadCookBook } from "~/lib/api/types/cookbook";
|
||||
import { HouseholdSummary } from "~/lib/api/types/household";
|
||||
|
||||
|
||||
export default defineComponent({
|
||||
components: { AppHeader, AppSidebar, LanguageDialog, TheSnackbar },
|
||||
|
@ -99,6 +104,15 @@ export default defineComponent({
|
|||
const route = useRoute();
|
||||
const groupSlug = computed(() => route.value.params.groupSlug || $auth.user?.groupSlug || "");
|
||||
const { cookbooks } = isOwnGroup.value ? useCookbooks() : usePublicCookbooks(groupSlug.value || "");
|
||||
const cookbookPreferences = useCookbookPreferences();
|
||||
const { store: households } = isOwnGroup.value ? useHouseholdStore() : usePublicHouseholdStore(groupSlug.value || "");
|
||||
|
||||
const householdsById = computed(() => {
|
||||
return households.value.reduce((acc, household) => {
|
||||
acc[household.id] = household;
|
||||
return acc;
|
||||
}, {} as { [key: string]: HouseholdSummary });
|
||||
});
|
||||
|
||||
const appInfo = useAppInfo();
|
||||
const showImageImport = computed(() => appInfo.value?.enableOpenaiImageServices);
|
||||
|
@ -113,29 +127,57 @@ export default defineComponent({
|
|||
sidebar.value = !$vuetify.breakpoint.md;
|
||||
});
|
||||
|
||||
const cookbookLinks = computed(() => {
|
||||
if (!cookbooks.value) return [];
|
||||
return cookbooks.value.map((cookbook) => {
|
||||
return {
|
||||
key: cookbook.slug,
|
||||
icon: $globals.icons.pages,
|
||||
title: cookbook.name,
|
||||
to: `/g/${groupSlug.value}/cookbooks/${cookbook.slug as string}`,
|
||||
};
|
||||
});
|
||||
});
|
||||
|
||||
interface Link {
|
||||
insertDivider: boolean;
|
||||
icon: string;
|
||||
title: string;
|
||||
subtitle: string | null;
|
||||
to: string;
|
||||
restricted: boolean;
|
||||
hide: boolean;
|
||||
function cookbookAsLink(cookbook: ReadCookBook): SideBarLink {
|
||||
return {
|
||||
key: cookbook.slug || "",
|
||||
icon: $globals.icons.pages,
|
||||
title: cookbook.name,
|
||||
to: `/g/${groupSlug.value}/cookbooks/${cookbook.slug || ""}`,
|
||||
restricted: false,
|
||||
};
|
||||
}
|
||||
|
||||
const createLinks = computed<Link[]>(() => [
|
||||
const currentUserHouseholdId = computed(() => $auth.user?.householdId);
|
||||
const cookbookLinks = computed<SideBarLink[]>(() => {
|
||||
if (!cookbooks.value) {
|
||||
return [];
|
||||
}
|
||||
cookbooks.value.sort((a, b) => (a.position || 0) - (b.position || 0));
|
||||
|
||||
const ownLinks: SideBarLink[] = [];
|
||||
const links: SideBarLink[] = [];
|
||||
const cookbooksByHousehold = cookbooks.value.reduce((acc, cookbook) => {
|
||||
const householdName = householdsById.value[cookbook.householdId]?.name || "";
|
||||
if (!acc[householdName]) {
|
||||
acc[householdName] = [];
|
||||
}
|
||||
acc[householdName].push(cookbook);
|
||||
return acc;
|
||||
}, {} as Record<string, ReadCookBook[]>);
|
||||
|
||||
Object.entries(cookbooksByHousehold).forEach(([householdName, cookbooks]) => {
|
||||
if (cookbooks[0].householdId === currentUserHouseholdId.value) {
|
||||
ownLinks.push(...cookbooks.map(cookbookAsLink));
|
||||
} else {
|
||||
links.push({
|
||||
key: householdName,
|
||||
icon: $globals.icons.book,
|
||||
title: householdName,
|
||||
children: cookbooks.map(cookbookAsLink),
|
||||
restricted: false,
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
links.sort((a, b) => a.title.localeCompare(b.title));
|
||||
if ($auth.user && cookbookPreferences.value.hideOtherHouseholds) {
|
||||
return ownLinks;
|
||||
} else {
|
||||
return [...ownLinks, ...links];
|
||||
}
|
||||
});
|
||||
|
||||
const createLinks = computed<SideBarLink[]>(() => [
|
||||
{
|
||||
insertDivider: false,
|
||||
icon: $globals.icons.link,
|
||||
|
@ -165,7 +207,7 @@ export default defineComponent({
|
|||
},
|
||||
]);
|
||||
|
||||
const bottomLinks = computed<SidebarLinks>(() => [
|
||||
const bottomLinks = computed<SideBarLink[]>(() => [
|
||||
{
|
||||
icon: $globals.icons.cog,
|
||||
title: i18n.tc("general.settings"),
|
||||
|
@ -174,7 +216,7 @@ export default defineComponent({
|
|||
},
|
||||
]);
|
||||
|
||||
const topLinks = computed<SidebarLinks>(() => [
|
||||
const topLinks = computed<SideBarLink[]>(() => [
|
||||
{
|
||||
icon: $globals.icons.silverwareForkKnife,
|
||||
to: `/g/${groupSlug.value}`,
|
||||
|
|
|
@ -135,7 +135,7 @@
|
|||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { computed, defineComponent, reactive, toRefs, useContext } from "@nuxtjs/composition-api";
|
||||
import { computed, defineComponent, reactive, toRefs, useContext, watch } from "@nuxtjs/composition-api";
|
||||
import { useLoggedInState } from "~/composables/use-logged-in-state";
|
||||
import { SidebarLinks } from "~/types/application-types";
|
||||
import UserAvatar from "~/components/Domain/User/UserAvatar.vue";
|
||||
|
@ -192,13 +192,29 @@ export default defineComponent({
|
|||
const userProfileLink = computed(() => $auth.user ? "/user/profile" : undefined);
|
||||
|
||||
const state = reactive({
|
||||
dropDowns: {},
|
||||
dropDowns: {} as Record<string, boolean>,
|
||||
topSelected: null as string[] | null,
|
||||
secondarySelected: null as string[] | null,
|
||||
bottomSelected: null as string[] | null,
|
||||
hasOpenedBefore: false as boolean,
|
||||
});
|
||||
|
||||
const allLinks = computed(() => [...props.topLink, ...(props.secondaryLinks || []), ...(props.bottomLinks || [])]);
|
||||
function initDropdowns() {
|
||||
allLinks.value.forEach((link) => {
|
||||
state.dropDowns[link.title] = link.childrenStartExpanded || false;
|
||||
})
|
||||
}
|
||||
watch(
|
||||
() => allLinks,
|
||||
() => {
|
||||
initDropdowns();
|
||||
},
|
||||
{
|
||||
deep: true,
|
||||
}
|
||||
);
|
||||
|
||||
return {
|
||||
...toRefs(state),
|
||||
userFavoritesLink,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue