useMenu.ts 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. import {Ref, ref} from "@vue/reactivity";
  2. import {useAccessProfileStore} from "~/stores/accessProfile";
  3. import {useRuntimeConfig} from "#app";
  4. import {useAbility} from "@casl/vue";
  5. import {useOrganizationProfileStore} from "~/stores/organizationProfile";
  6. import AbstractMenuBuilder from "~/services/menuBuilder/abstractMenuBuilder";
  7. import {MenuGroup, MenuItem} from "~/types/layout";
  8. import {usePageStore} from "~/stores/page";
  9. import menus from "~/services/menuBuilder/_import";
  10. import {MENU_LINK_TYPE} from "~/types/enum/layout";
  11. /**
  12. * Renvoie des méthodes pour interagir avec les menus
  13. *
  14. * Exemple d'usage :
  15. *
  16. * const { buildMenu, hasMenu } = useMenuBuilder()
  17. * const menu = buildMenu('Main')
  18. *
  19. * console.log(hasMenu('Main')) // true
  20. */
  21. export const useMenu = () => {
  22. const runtimeConfig = useRuntimeConfig()
  23. const ability = useAbility()
  24. const organizationProfile = useOrganizationProfileStore()
  25. const accessProfile = useAccessProfileStore()
  26. const pageState = usePageStore()
  27. const getBuilder = (name: string): AbstractMenuBuilder => {
  28. if (!(name in menus)) {
  29. throw new Error('Unknown menu : ' + name)
  30. }
  31. const menuBuilder = menus[name]
  32. // @ts-ignore
  33. return new menuBuilder(runtimeConfig, ability, organizationProfile, accessProfile)
  34. }
  35. /**
  36. * Construit un menu à partir de son nom
  37. * Met à jour le store pour garder en mémoire la présence de ce menu et son état
  38. *
  39. * @param name
  40. */
  41. const buildMenu = (name: string): Ref<MenuGroup> => {
  42. const builder = getBuilder(name)
  43. const menu = builder.build() as MenuGroup
  44. // On enregistre l'état du menu dans le store de la page
  45. if (menu !== null && (menu.children ?? []).length > 0) {
  46. pageState.menusOpened[builder.getMenuName()] = false
  47. console.log('Menu ' + builder.getMenuName() + ' built (' + (menu.children ?? []).length+ ' entries)')
  48. }
  49. return ref(menu)
  50. }
  51. /**
  52. * L'utilisateur en cours a-t-il accès au menu portant ce nom ?
  53. *
  54. * @param name
  55. */
  56. const hasMenu = (name: string): boolean => {
  57. return name in pageState.menusOpened
  58. }
  59. /**
  60. * Soulève une erreur si aucun menu portant ce nom n'est enregistré dans le store
  61. *
  62. * @param name
  63. */
  64. const assertExists = (name: string) => {
  65. if (!(name in pageState.menusOpened)) {
  66. throw new Error('Unknown menu : ' + name)
  67. }
  68. }
  69. /**
  70. * Retourne vrai si le menu est actuellement ouvert / déplié
  71. *
  72. * @param name
  73. */
  74. const isMenuOpened = (name: string): boolean => {
  75. assertExists(name)
  76. return pageState.menusOpened[name]
  77. }
  78. /**
  79. * Met à jour l'état du menu portant ce nom
  80. *
  81. * @param name
  82. * @param state
  83. */
  84. const setMenuState = (name: string, state: boolean) => {
  85. assertExists(name)
  86. pageState.menusOpened[name] = state
  87. }
  88. /**
  89. * Ouvre / déplie le menu portant ce nom
  90. *
  91. * @param name
  92. */
  93. const openMenu = (name: string) => {
  94. setMenuState(name, true)
  95. }
  96. /**
  97. * Ferme / replie le menu portant ce nom
  98. *
  99. * @param name
  100. */
  101. const closeMenu = (name: string) => {
  102. setMenuState(name, false)
  103. }
  104. /**
  105. * Bascule l'état du menu entre ouvert et fermé
  106. *
  107. * @param name
  108. */
  109. const toggleMenu = (name: string) => {
  110. setMenuState(name, !pageState.menusOpened[name])
  111. }
  112. /**
  113. * Le lien menuItem est-il un lien interne à l'application
  114. *
  115. * @param menuItem
  116. */
  117. const isInternalLink = (menuItem: MenuItem | MenuGroup): boolean => {
  118. return 'type' in menuItem && menuItem.type === MENU_LINK_TYPE.INTERNAL
  119. }
  120. return {
  121. buildMenu,
  122. hasMenu,
  123. setMenuState,
  124. openMenu,
  125. closeMenu,
  126. toggleMenu,
  127. isMenuOpened,
  128. isInternalLink
  129. }
  130. }