Maintenance: Desktop view - Popover instance is bound to wrong owner
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
<!-- Copyright (C) 2012-2025 Zammad Foundation, https://zammad-foundation.org/ -->
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed, type SetupContext, toRefs, useSlots } from 'vue'
|
||||
import { computed, toRefs, useSlots } from 'vue'
|
||||
|
||||
import type { ObjectLike } from '#shared/types/utils.ts'
|
||||
|
||||
@@ -27,14 +27,13 @@ const emit = defineEmits<{
|
||||
|
||||
const { items, entity } = toRefs(props)
|
||||
|
||||
const { filteredMenuItems } = usePopoverMenu(items, entity)
|
||||
// If no explicit items prop is provided, inject from a parent provider (e.g., CommonActionMenu)
|
||||
// Otherwise, create an independent instance for this component
|
||||
const { filteredMenuItems } = usePopoverMenu(items, entity, {
|
||||
injects: !items.value?.length,
|
||||
})
|
||||
|
||||
/**
|
||||
* Workaround to satisfy linter
|
||||
* @bug https://github.com/vuejs/language-tools/issues/5082
|
||||
* Wait to be closed
|
||||
* */
|
||||
const slots: SetupContext['slots'] = useSlots()
|
||||
const slots = useSlots()
|
||||
|
||||
const showHeaderLabel = computed(() => {
|
||||
if (!filteredMenuItems.value && !slots.default) return false
|
||||
|
||||
@@ -14,13 +14,13 @@ const POPOVER_MENU_SYMBOL = Symbol('popover-menu')
|
||||
export const usePopoverMenu = (
|
||||
items: Ref<MenuItem[] | undefined>,
|
||||
entity: Ref<ObjectLike | undefined>,
|
||||
options: { provides?: boolean } = {},
|
||||
options: { provides?: boolean; injects?: boolean } = {},
|
||||
) => {
|
||||
const { provides = false, injects = false } = options
|
||||
|
||||
const injectPopoverMenu = inject<Maybe<UsePopoverMenuReturn>>(POPOVER_MENU_SYMBOL, null)
|
||||
|
||||
if (injectPopoverMenu) return injectPopoverMenu
|
||||
|
||||
const { provides = false } = options
|
||||
if (injects && injectPopoverMenu) return injectPopoverMenu
|
||||
|
||||
const session = useSessionStore()
|
||||
|
||||
|
||||
@@ -32,9 +32,11 @@ interface Props {
|
||||
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
visible: true,
|
||||
targetId: getUuid(),
|
||||
})
|
||||
|
||||
// Generate unique targetId per component instance to avoid cross-editor targeting
|
||||
const targetId = computed(() => props.targetId || `editor-action-menu-${getUuid()}`)
|
||||
|
||||
const emit = defineEmits<{
|
||||
hide: []
|
||||
blur: []
|
||||
@@ -114,7 +116,7 @@ onKeyUp(['ArrowDown', 'ArrowUp', 'ArrowLeft', 'ArrowRight'], (e) => {
|
||||
useEventListener('click', (e) => {
|
||||
const target = e.target as HTMLDivElement
|
||||
|
||||
const targetElementWithId = target.closest(`#${CSS.escape(props.targetId)}`)
|
||||
const targetElementWithId = target.closest(`#${CSS.escape(targetId.value)}`)
|
||||
|
||||
if (targetElementWithId) {
|
||||
setPopoverTarget(targetElementWithId as HTMLDivElement)
|
||||
@@ -126,7 +128,7 @@ useEventListener('click', (e) => {
|
||||
|
||||
const handleMenuItemClick = (action: MenuItem, event: MouseEvent) => {
|
||||
if ((action as ActionItem).subMenu) {
|
||||
const newPopoverTarget = document.getElementById(`${CSS.escape(props.targetId)}`)
|
||||
const newPopoverTarget = document.getElementById(`${CSS.escape(targetId.value)}`)
|
||||
if (newPopoverTarget) {
|
||||
popoverTarget.value = newPopoverTarget as HTMLDivElement
|
||||
}
|
||||
|
||||
@@ -10852,7 +10852,7 @@ msgstr ""
|
||||
msgid "No import in progress."
|
||||
msgstr ""
|
||||
|
||||
#: app/frontend/apps/desktop/components/CommonPopoverMenu/CommonPopoverMenu.vue:160
|
||||
#: app/frontend/apps/desktop/components/CommonPopoverMenu/CommonPopoverMenu.vue:159
|
||||
msgid "No items available"
|
||||
msgstr ""
|
||||
|
||||
|
||||
Reference in New Issue
Block a user