feat(editor): Show execution hint message in FocusPanel (no-changelog) (#17442)

This commit is contained in:
Charlie Kolb
2025-07-21 11:48:46 +02:00
committed by GitHub
parent 5cf74beec1
commit b14ad784cb
4 changed files with 79 additions and 31 deletions

View File

@@ -1,7 +1,7 @@
<script setup lang="ts">
import { useFocusPanelStore } from '@/stores/focusPanel.store';
import { useNodeTypesStore } from '@/stores/nodeTypes.store';
import { N8nText, N8nInput, N8nResizeWrapper } from '@n8n/design-system';
import { N8nText, N8nInput, N8nResizeWrapper, N8nInfoTip } from '@n8n/design-system';
import { computed, nextTick, ref, watch, toRef } from 'vue';
import { useI18n } from '@n8n/i18n';
import {
@@ -29,6 +29,8 @@ import { htmlEditorEventBus } from '@/event-bus';
import { hasFocusOnInput, isFocusableEl } from '@/utils/typesUtils';
import type { ResizeData, TargetNodeParameterContext } from '@/Interface';
import { useThrottleFn } from '@vueuse/core';
import { useExecutionData } from '@/composables/useExecutionData';
import { useWorkflowsStore } from '@/stores/workflows.store';
defineOptions({ name: 'FocusPanel' });
@@ -48,6 +50,7 @@ const inputField = ref<InstanceType<typeof N8nInput> | HTMLElement>();
const locale = useI18n();
const nodeHelpers = useNodeHelpers();
const focusPanelStore = useFocusPanelStore();
const workflowsStore = useWorkflowsStore();
const nodeTypesStore = useNodeTypesStore();
const nodeSettingsParameters = useNodeSettingsParameters();
const environmentsStore = useEnvironmentsStore();
@@ -108,6 +111,10 @@ const isExecutable = computed(() => {
);
});
const node = computed(() => resolvedParameter.value?.node);
const { hasNodeRun } = useExecutionData({ node });
function getTypeOption<T>(optionName: string): T | undefined {
return resolvedParameter.value
? getParameterTypeOption<T>(resolvedParameter.value.parameter, optionName)
@@ -172,6 +179,8 @@ const targetNodeParameterContext = computed<TargetNodeParameterContext | undefin
};
});
const isNodeExecuting = computed(() => workflowsStore.isNodeExecuting(node.value?.name ?? ''));
const { resolvedExpression } = useResolvedExpression({
expression,
additionalData: resolvedAdditionalExpressionData,
@@ -345,7 +354,15 @@ const onResizeThrottle = useThrottleFn(onResize, 10);
</div>
<div :class="$style.parameterDetailsWrapper">
<div :class="$style.parameterOptionsWrapper">
<div></div>
<div :class="$style.noExecutionDataTip">
<N8nInfoTip
v-if="!hasNodeRun && !isNodeExecuting"
:class="$style.delayedShow"
:bold="true"
>
{{ locale.baseText('nodeView.focusPanel.noExecutionData') }}
</N8nInfoTip>
</div>
<ParameterOptions
v-if="isDisplayed"
:parameter="resolvedParameter.parameter"
@@ -575,6 +592,10 @@ const onResizeThrottle = useThrottleFn(onResize, 10);
justify-content: space-between;
}
.noExecutionDataTip {
align-content: center;
}
.editorContainer {
height: 100%;
overflow-y: auto;
@@ -594,6 +615,20 @@ const onResizeThrottle = useThrottleFn(onResize, 10);
}
}
// We have this animation here to hide the short time between no longer
// executing the node and having runData available
.delayedShow {
opacity: 0;
transition: opacity 0.1s none;
animation: triggerShow 0.1s normal 0.1s forwards;
}
@keyframes triggerShow {
to {
opacity: 1;
}
}
.closeButton {
cursor: pointer;
}