mirror of
https://github.com/Abdulazizzn/n8n-enterprise-unlocked.git
synced 2025-12-16 17:46:45 +00:00
feat(editor): Show execution hint message in FocusPanel (no-changelog) (#17442)
This commit is contained in:
@@ -1502,6 +1502,7 @@
|
||||
"nodeView.couldntImportWorkflow": "Could not import workflow",
|
||||
"nodeView.couldntLoadWorkflow.invalidWorkflowObject": "Invalid workflow object",
|
||||
"nodeView.deletesTheCurrentExecutionData": "Deletes the current execution data",
|
||||
"nodeView.focusPanel.noExecutionData": "Execute previous node for autocomplete",
|
||||
"nodeView.focusPanel.noParameters.title": "Show a node parameter here, to iterate easily",
|
||||
"nodeView.focusPanel.noParameters.subtitle": "For example, keep your prompt always visible so you can run the workflow while tweaking it",
|
||||
"nodeView.focusPanel.missingParameter": "This parameter is no longer visible on the node. A related parameter was likely changed, removing this one.",
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -1,11 +1,6 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, computed, onMounted, watch } from 'vue';
|
||||
import {
|
||||
NodeConnectionTypes,
|
||||
type IRunData,
|
||||
type IRunExecutionData,
|
||||
type Workflow,
|
||||
} from 'n8n-workflow';
|
||||
import { NodeConnectionTypes, type IRunData, type Workflow } from 'n8n-workflow';
|
||||
import RunData from './RunData.vue';
|
||||
import RunInfo from './RunInfo.vue';
|
||||
import { storeToRefs } from 'pinia';
|
||||
@@ -26,6 +21,7 @@ import { NDV_UI_OVERHAUL_EXPERIMENT } from '@/constants';
|
||||
import { usePostHog } from '@/stores/posthog.store';
|
||||
import { type IRunDataDisplayMode } from '@/Interface';
|
||||
import { I18nT } from 'vue-i18n';
|
||||
import { useExecutionData } from '@/composables/useExecutionData';
|
||||
|
||||
// Types
|
||||
|
||||
@@ -111,6 +107,7 @@ const collapsingColumnName = ref<string | null>(null);
|
||||
const node = computed(() => {
|
||||
return ndvStore.activeNode ?? undefined;
|
||||
});
|
||||
const { hasNodeRun, workflowExecution, workflowRunData } = useExecutionData({ node });
|
||||
|
||||
const isTriggerNode = computed(() => {
|
||||
return !!node.value && nodeTypesStore.isTriggerNode(node.value.type);
|
||||
@@ -149,29 +146,6 @@ const isNodeRunning = computed(() => {
|
||||
|
||||
const workflowRunning = computed(() => workflowsStore.isWorkflowRunning);
|
||||
|
||||
const workflowExecution = computed(() => {
|
||||
return workflowsStore.getWorkflowExecution;
|
||||
});
|
||||
|
||||
const workflowRunData = computed(() => {
|
||||
if (workflowExecution.value === null) {
|
||||
return null;
|
||||
}
|
||||
const executionData: IRunExecutionData | undefined = workflowExecution.value.data;
|
||||
if (!executionData?.resultData?.runData) {
|
||||
return null;
|
||||
}
|
||||
return executionData.resultData.runData;
|
||||
});
|
||||
|
||||
const hasNodeRun = computed(() => {
|
||||
if (workflowsStore.subWorkflowExecutionError) return true;
|
||||
|
||||
return Boolean(
|
||||
node.value && workflowRunData.value && workflowRunData.value.hasOwnProperty(node.value.name),
|
||||
);
|
||||
});
|
||||
|
||||
const runTaskData = computed(() => {
|
||||
if (!node.value || workflowExecution.value === null) {
|
||||
return null;
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
import { useWorkflowsStore } from '@/stores/workflows.store';
|
||||
import type { INode, IRunExecutionData } from 'n8n-workflow';
|
||||
import { computed, type ComputedRef } from 'vue';
|
||||
|
||||
export function useExecutionData({ node }: { node: ComputedRef<INode | undefined> }) {
|
||||
const workflowsStore = useWorkflowsStore();
|
||||
|
||||
const workflowExecution = computed(() => {
|
||||
return workflowsStore.getWorkflowExecution;
|
||||
});
|
||||
|
||||
const workflowRunData = computed(() => {
|
||||
if (workflowExecution.value === null) {
|
||||
return null;
|
||||
}
|
||||
const executionData: IRunExecutionData | undefined = workflowExecution.value.data;
|
||||
if (!executionData?.resultData?.runData) {
|
||||
return null;
|
||||
}
|
||||
return executionData.resultData.runData;
|
||||
});
|
||||
|
||||
const hasNodeRun = computed(() => {
|
||||
if (workflowsStore.subWorkflowExecutionError) return true;
|
||||
|
||||
return Boolean(
|
||||
node.value &&
|
||||
workflowRunData.value &&
|
||||
Object.prototype.hasOwnProperty.bind(workflowRunData.value)(node.value.name),
|
||||
);
|
||||
});
|
||||
|
||||
return {
|
||||
workflowExecution,
|
||||
workflowRunData,
|
||||
hasNodeRun,
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user