fix(editor): Make JSON copy button work in PiP window (#16887)

This commit is contained in:
Suguru Inoue
2025-07-02 09:53:28 +02:00
committed by GitHub
parent ee463f08b6
commit 8fda3fb2aa

View File

@@ -9,12 +9,14 @@ import { useNDVStore } from '@/stores/ndv.store';
import { useNodeHelpers } from '@/composables/useNodeHelpers'; import { useNodeHelpers } from '@/composables/useNodeHelpers';
import { useToast } from '@/composables/useToast'; import { useToast } from '@/composables/useToast';
import { useI18n } from '@n8n/i18n'; import { useI18n } from '@n8n/i18n';
import { nonExistingJsonPath } from '@/constants'; import { nonExistingJsonPath, PiPWindowSymbol } from '@/constants';
import { useClipboard } from '@/composables/useClipboard'; import { useClipboard } from '@/composables/useClipboard';
import { usePinnedData } from '@/composables/usePinnedData'; import { usePinnedData } from '@/composables/usePinnedData';
import { computed } from 'vue'; import { inject, computed } from 'vue';
import { useRoute } from 'vue-router'; import { useRoute } from 'vue-router';
import { useTelemetry } from '@/composables/useTelemetry'; import { useTelemetry } from '@/composables/useTelemetry';
import { N8nIconButton } from '@n8n/design-system';
import { ElDropdown, ElDropdownItem, ElDropdownMenu } from 'element-plus';
type JsonPathData = { type JsonPathData = {
path: string; path: string;
@@ -36,6 +38,10 @@ const props = withDefaults(
selectedJsonPath: nonExistingJsonPath, selectedJsonPath: nonExistingJsonPath,
}, },
); );
const pipWindow = inject(PiPWindowSymbol);
const isInPiPWindow = computed(() => pipWindow?.value !== undefined);
const ndvStore = useNDVStore(); const ndvStore = useNDVStore();
const workflowsStore = useWorkflowsStore(); const workflowsStore = useWorkflowsStore();
@@ -177,7 +183,7 @@ function handleCopyClick(commandData: { command: string }) {
<template> <template>
<div :class="$style.actionsGroup" data-test-id="ndv-json-actions"> <div :class="$style.actionsGroup" data-test-id="ndv-json-actions">
<n8n-icon-button <N8nIconButton
v-if="noSelection" v-if="noSelection"
:title="i18n.baseText('runData.copyToClipboard')" :title="i18n.baseText('runData.copyToClipboard')"
icon="files" icon="files"
@@ -185,9 +191,16 @@ function handleCopyClick(commandData: { command: string }) {
:circle="false" :circle="false"
@click="handleCopyClick({ command: 'value' })" @click="handleCopyClick({ command: 'value' })"
/> />
<el-dropdown v-else trigger="click" @command="handleCopyClick"> <ElDropdown
v-else
trigger="click"
:teleported="
!isInPiPWindow // disabling teleport ensures the menu is rendered in PiP window
"
@command="handleCopyClick"
>
<span class="el-dropdown-link"> <span class="el-dropdown-link">
<n8n-icon-button <N8nIconButton
:title="i18n.baseText('runData.copyToClipboard')" :title="i18n.baseText('runData.copyToClipboard')"
icon="files" icon="files"
type="tertiary" type="tertiary"
@@ -195,32 +208,30 @@ function handleCopyClick(commandData: { command: string }) {
/> />
</span> </span>
<template #dropdown> <template #dropdown>
<el-dropdown-menu> <ElDropdownMenu>
<el-dropdown-item :command="{ command: 'value' }"> <ElDropdownItem :command="{ command: 'value' }">
{{ i18n.baseText('runData.copyValue') }} {{ i18n.baseText('runData.copyValue') }}
</el-dropdown-item> </ElDropdownItem>
<el-dropdown-item :command="{ command: 'itemPath' }" divided> <ElDropdownItem :command="{ command: 'itemPath' }" divided>
{{ i18n.baseText('runData.copyItemPath') }} {{ i18n.baseText('runData.copyItemPath') }}
</el-dropdown-item> </ElDropdownItem>
<el-dropdown-item :command="{ command: 'parameterPath' }"> <ElDropdownItem :command="{ command: 'parameterPath' }">
{{ i18n.baseText('runData.copyParameterPath') }} {{ i18n.baseText('runData.copyParameterPath') }}
</el-dropdown-item> </ElDropdownItem>
</el-dropdown-menu> </ElDropdownMenu>
</template> </template>
</el-dropdown> </ElDropdown>
</div> </div>
</template> </template>
<style lang="scss" module> <style lang="scss" module>
.actionsGroup { .actionsGroup {
position: sticky; position: absolute;
height: 0;
overflow: visible;
z-index: 10; z-index: 10;
top: 0; top: 0;
right: 0;
padding-right: var(--spacing-s); padding-right: var(--spacing-s);
opacity: 0; opacity: 0;
transition: opacity 0.3s ease; transition: opacity 0.3s ease;
text-align: right;
} }
</style> </style>