import {Ref, ref} from "@vue/reactivity"; import {useAccessProfileStore} from "~/stores/accessProfile"; import {useRuntimeConfig} from "#app"; import {useAbility} from "@casl/vue"; import {useOrganizationProfileStore} from "~/stores/organizationProfile"; import AbstractMenuBuilder from "~/services/menuBuilder/abstractMenuBuilder"; import {MenuGroup, MenuItem} from "~/types/layout"; import {usePageStore} from "~/stores/page"; import menus from "~/services/menuBuilder/_import"; import {MENU_LINK_TYPE} from "~/types/enum/layout"; /** * Renvoie des méthodes pour interagir avec les menus * * Exemple d'usage : * * const { buildMenu, hasMenu } = useMenuBuilder() * const menu = buildMenu('Main') * * console.log(hasMenu('Main')) // true */ export const useMenu = () => { const runtimeConfig = useRuntimeConfig() const ability = useAbility() const organizationProfile = useOrganizationProfileStore() const accessProfile = useAccessProfileStore() const pageState = usePageStore() const getBuilder = (name: string): AbstractMenuBuilder => { if (!(name in menus)) { throw new Error('Unknown menu : ' + name) } const menuBuilder = menus[name] // @ts-ignore return new menuBuilder(runtimeConfig, ability, organizationProfile, accessProfile) } /** * Construit un menu à partir de son nom * Met à jour le store pour garder en mémoire la présence de ce menu et son état * * @param name */ const buildMenu = (name: string): Ref => { const builder = getBuilder(name) const menu = builder.build() as MenuGroup // On enregistre l'état du menu dans le store de la page if (menu !== null && (menu.children ?? []).length > 0) { pageState.menusOpened[builder.getMenuName()] = false console.log('Menu ' + builder.getMenuName() + ' built (' + (menu.children ?? []).length+ ' entries)') } return ref(menu) } /** * L'utilisateur en cours a-t-il accès au menu portant ce nom ? * * @param name */ const hasMenu = (name: string): boolean => { return name in pageState.menusOpened } /** * Soulève une erreur si aucun menu portant ce nom n'est enregistré dans le store * * @param name */ const assertExists = (name: string) => { if (!(name in pageState.menusOpened)) { throw new Error('Unknown menu : ' + name) } } /** * Retourne vrai si le menu est actuellement ouvert / déplié * * @param name */ const isMenuOpened = (name: string): boolean => { assertExists(name) return pageState.menusOpened[name] } /** * Met à jour l'état du menu portant ce nom * * @param name * @param state */ const setMenuState = (name: string, state: boolean) => { assertExists(name) pageState.menusOpened[name] = state } /** * Ouvre / déplie le menu portant ce nom * * @param name */ const openMenu = (name: string) => { setMenuState(name, true) } /** * Ferme / replie le menu portant ce nom * * @param name */ const closeMenu = (name: string) => { setMenuState(name, false) } /** * Bascule l'état du menu entre ouvert et fermé * * @param name */ const toggleMenu = (name: string) => { setMenuState(name, !pageState.menusOpened[name]) } /** * Le lien menuItem est-il un lien interne à l'application * * @param menuItem */ const isInternalLink = (menuItem: MenuItem | MenuGroup): boolean => { return 'type' in menuItem && menuItem.type === MENU_LINK_TYPE.INTERNAL } return { buildMenu, hasMenu, setMenuState, openMenu, closeMenu, toggleMenu, isMenuOpened, isInternalLink } }