CommonSectionMenu.vue 2.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. <!-- Copyright (C) 2012-2024 Zammad Foundation, https://zammad-foundation.org/ -->
  2. <script setup lang="ts">
  3. import { computed, useSlots } from 'vue'
  4. import { useSessionStore } from '#shared/stores/session.ts'
  5. import CommonSectionMenuLink from './CommonSectionMenuLink.vue'
  6. import type { MenuItem } from './types.ts'
  7. import type { RouteLocationRaw } from 'vue-router'
  8. export interface Props {
  9. actionLabel?: string
  10. actionLink?: RouteLocationRaw
  11. headerLabel?: string
  12. items?: MenuItem[]
  13. help?: string
  14. }
  15. const props = defineProps<Props>()
  16. const emit = defineEmits<{
  17. 'action-click': [MouseEvent]
  18. }>()
  19. const clickOnAction = (event: MouseEvent) => {
  20. emit('action-click', event)
  21. }
  22. const session = useSessionStore()
  23. const itemsWithPermission = computed(() => {
  24. if (!props.items || !props.items.length) return null
  25. return props.items.filter((item) => {
  26. if (item.permission) {
  27. return session.hasPermission(item.permission)
  28. }
  29. return true
  30. })
  31. })
  32. const slots = useSlots()
  33. const hasHelp = computed(() => slots.help || props.help)
  34. const showLabel = computed(() => {
  35. if (!itemsWithPermission.value && !slots.default && !slots['before-items'])
  36. return false
  37. return slots.header || props.headerLabel || props.actionLabel
  38. })
  39. </script>
  40. <template>
  41. <div v-if="showLabel" class="mb-2 flex flex-row justify-between">
  42. <div class="text-white/80 ltr:pl-3 rtl:pr-3">
  43. <slot name="header">{{ i18n.t(headerLabel) }}</slot>
  44. </div>
  45. <component
  46. :is="actionLink ? 'CommonLink' : 'div'"
  47. v-if="actionLabel"
  48. :link="actionLink"
  49. class="text-blue cursor-pointer ltr:pr-4 rtl:pl-4"
  50. @click="clickOnAction"
  51. >
  52. {{ i18n.t(actionLabel) }}
  53. </component>
  54. </div>
  55. <div
  56. v-if="itemsWithPermission || $slots.default || $slots['before-items']"
  57. class="flex w-full flex-col overflow-hidden rounded-xl bg-gray-500 text-base text-white"
  58. :class="{ 'mb-6': !hasHelp }"
  59. v-bind="$attrs"
  60. >
  61. <slot name="before-items" />
  62. <slot>
  63. <template v-for="(item, idx) in itemsWithPermission" :key="idx">
  64. <CommonSectionMenuLink
  65. v-if="item.type === 'link'"
  66. :label="item.label"
  67. :link="item.link"
  68. :icon="item.icon"
  69. :icon-bg="item.iconBg"
  70. :information="item.information"
  71. :label-placeholder="item.labelPlaceholder"
  72. @click="item.onClick?.($event)"
  73. />
  74. </template>
  75. </slot>
  76. </div>
  77. <div v-if="hasHelp" class="mb-4 pt-1 text-xs text-gray-100 ltr:pl-3 rtl:pr-3">
  78. <slot name="help">
  79. {{ $t(help) }}
  80. </slot>
  81. </div>
  82. </template>